ETH Price: $3,028.28 (-2.73%)
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

Transaction Hash
Method
Block
From
To
Approve383186512025-11-18 0:44:091 hr ago1763426649IN
friend.tech: FRIEND Token
0 ETH0.000000590.01169254
Approve383152522025-11-17 22:50:512 hrs ago1763419851IN
friend.tech: FRIEND Token
0 ETH0.000000080.00172009
Approve383107662025-11-17 20:21:195 hrs ago1763410879IN
friend.tech: FRIEND Token
0 ETH0.000002020.03977469
Approve383102932025-11-17 20:05:335 hrs ago1763409933IN
friend.tech: FRIEND Token
0 ETH0.000016470.32455959
Approve383018592025-11-17 15:24:2510 hrs ago1763393065IN
friend.tech: FRIEND Token
0 ETH0.000000420.00830412
Approve382968082025-11-17 12:36:0313 hrs ago1763382963IN
friend.tech: FRIEND Token
0 ETH0.000000080.00175307
Approve382908692025-11-17 9:18:0516 hrs ago1763371085IN
friend.tech: FRIEND Token
0 ETH0.000000080.00176215
Approve382781712025-11-17 2:14:4923 hrs ago1763345689IN
friend.tech: FRIEND Token
0 ETH0.000000230.0080893
Approve382603572025-11-16 16:21:0133 hrs ago1763310061IN
friend.tech: FRIEND Token
0 ETH0.000000450.00883555
Approve382473872025-11-16 9:08:4140 hrs ago1763284121IN
friend.tech: FRIEND Token
0 ETH0.000000060.00124143
Approve382434232025-11-16 6:56:3342 hrs ago1763276193IN
friend.tech: FRIEND Token
0 ETH0.000000250.00493886
Approve382274312025-11-15 22:03:292 days ago1763244209IN
friend.tech: FRIEND Token
0 ETH0.000000190.00393192
Approve382255852025-11-15 21:01:572 days ago1763240517IN
friend.tech: FRIEND Token
0 ETH0.000000080.00169118
Approve382228582025-11-15 19:31:032 days ago1763235063IN
friend.tech: FRIEND Token
0 ETH0.000000030.00123387
Approve382228172025-11-15 19:29:412 days ago1763234981IN
friend.tech: FRIEND Token
0 ETH0.000000060.00126449
Transfer382227272025-11-15 19:26:412 days ago1763234801IN
friend.tech: FRIEND Token
0 ETH0.000000140.00252387
Approve382183152025-11-15 16:59:372 days ago1763225977IN
friend.tech: FRIEND Token
0 ETH0.00000020.004
Approve382144832025-11-15 14:51:532 days ago1763218313IN
friend.tech: FRIEND Token
0 ETH0.00000020.00398323
Approve382111812025-11-15 13:01:492 days ago1763211709IN
friend.tech: FRIEND Token
0 ETH0.000000090.001846
Approve382107562025-11-15 12:47:392 days ago1763210859IN
friend.tech: FRIEND Token
0 ETH0.000000070.00264491
Approve382107522025-11-15 12:47:312 days ago1763210851IN
friend.tech: FRIEND Token
0 ETH0.000000070.00264402
Approve382106352025-11-15 12:43:372 days ago1763210617IN
friend.tech: FRIEND Token
0 ETH0.000000130.00275198
Approve382106262025-11-15 12:43:192 days ago1763210599IN
friend.tech: FRIEND Token
0 ETH0.000000140.00279636
Approve382014082025-11-15 7:36:032 days ago1763192163IN
friend.tech: FRIEND Token
0 ETH0.000000090.00177198
Transfer381889952025-11-15 0:42:173 days ago1763167337IN
friend.tech: FRIEND Token
0 ETH0.000000110.00229512

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

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

Contract Name:
Points

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

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

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

/// @title Points
/// @author CopyPaste
/// @notice A Standard Implementation of Points for FriendTechV2
contract Points is Owned(msg.sender), IPoints {
    /*//////////////////////////////////////////////////////////////
                                 STORAGE
    //////////////////////////////////////////////////////////////*/
    /// Merkle Root for the point claims
    bytes32 public immutable merkleRootA;
    bytes32 public immutable merkleRootB;

    mapping(address user => uint256 balance) public balanceOf;

    mapping(address owner => mapping(address spender => uint256 amount)) public allowance;

    mapping(address user => bool hasClaimedA) public claimedA;
    mapping(address user => bool hasClaimedB) public claimedB;

    /// The totalSupply of points
    uint256 public totalSupply;

    /*//////////////////////////////////////////////////////////////
                                 CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/
    /*
     * @param _merkleRootA The merkle root for first the point claims
     * @param _merkleRootB The merkle root for second the point claims
     */
    constructor(bytes32 _merkleRootA, bytes32 _merkleRootB) {
        merkleRootA = _merkleRootA;
        merkleRootB = _merkleRootB;
    }

    /*//////////////////////////////////////////////////////////////
                                METADATA
    //////////////////////////////////////////////////////////////*/

    string public name = "Points";
    string public symbol = "PTS";
    uint8 public decimals = 18;

    /*//////////////////////////////////////////////////////////////
                             ACCESS CONTROL
    //////////////////////////////////////////////////////////////*/
    mapping(address _contract => bool isWhitelisted) public isAllowed;
    mapping(bytes4 functionSignature => bool canBeCalled) public isOpen;

    modifier onlyWhitelisted() {
        require(isAllowed[msg.sender] || isOpen[msg.sig], "WHITELIST");
        _;
    }

    /*
     * @param _contract The contract address allowed to interact with points
     * @param toggle The toggle for whether or not the contract is allowed
     */
    function toggleContract(address _contract, bool toggle) external onlyOwner {
        isAllowed[_contract] = toggle;
    }

    /*
     * @param function The function to open to the public
     * @param toggle The toggle for whether or not the contract is allowed
     */
    function toggleFunction(bytes4 functionSig, bool toggle) external onlyOwner {
        isOpen[functionSig] = toggle;
    }

    /*
     * @param to address to recieve the points
     * @param amount The amount of points to mint
     */
    function mint(address to, uint256 amount) external onlyOwner {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    /*//////////////////////////////////////////////////////////////
                             TRANSFER LOGIC
    //////////////////////////////////////////////////////////////*/
    /*
     * @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 {
        require(!claimedA[msg.sender], "Points: already claimed");
        require(giftAmount <= amount, "Points: gift amount exceeds claim"); // Would underflow anyway but you can never be too safe
        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, amount))));
        require(MerkleProofLib.verifyCalldata(proof, merkleRootA, leaf), "Points: invalid proof");

        claimedA[msg.sender] = true;

        if (giftAmount != 0) {
            uint256 perUser = giftAmount / giftRecipients.length;

            amount -= giftAmount;

            for (uint256 i = 0; i < giftRecipients.length; ) {
                balanceOf[giftRecipients[i]] += perUser;

                unchecked {
                    ++i;
                }
            }
        }

        totalSupply += amount + giftAmount;

        // Mint the points to the recipient
        unchecked {
            balanceOf[recipient] += amount;
        }

        emit ClaimedA(msg.sender, recipient, amount);
    }

    /*
     * @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 claimB(bytes32[] calldata proof, address recipient, uint256 amount, address[] calldata giftRecipients, uint256 giftAmount) external {
        require(!claimedB[msg.sender], "Points: already claimed");
        require(giftAmount <= amount, "Points: gift amount exceeds claim"); // Would underflow anyway but you can never be too safe

        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, amount))));
        require(MerkleProofLib.verifyCalldata(proof, merkleRootB, leaf), "Points: invalid proof");

        claimedB[msg.sender] = true;

        if (giftAmount != 0) {
            uint256 perUser = giftAmount / giftRecipients.length;

            amount -= giftAmount;

            for (uint256 i = 0; i < giftRecipients.length; ) {
                balanceOf[giftRecipients[i]] += perUser;

                unchecked {
                    ++i;
                }
            }
        }

        totalSupply += amount + giftAmount;

        // Mint the points to the recipient
        unchecked {
            balanceOf[recipient] += amount;
        }

        emit ClaimedB(msg.sender, recipient, amount);
    }

    /*
     * @notice Unlike ERC20, Points do not return a boolean on transfer
     * @param to The address that will receive the points
     * @param amount The amount of points to transfer
     */
    function transfer(address to, uint256 amount) external onlyWhitelisted {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);
    }

    /*
     * @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 amount The amount of points to transfer
     */
    function transferFrom(address from, address to, uint256 amount) external onlyWhitelisted {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);
    }

    /*
     * @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 onlyWhitelisted {
        allowance[msg.sender][spender] = amount;

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            MERKLE PROOF VERIFICATION OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(proof) {
                // Initialize `offset` to the offset of `proof` elements in memory.
                let offset := add(proof, 0x20)
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(offset, shl(5, mload(proof)))
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, mload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), mload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if proof.length {
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(proof.offset, shl(5, proof.length))
                // Initialize `offset` to the offset of `proof` in the calldata.
                let offset := proof.offset
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, calldataload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), calldataload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - The sum of the lengths of `proof` and `leaves` must never overflow.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The memory offset of `proof` must be non-zero
    ///   (i.e. `proof` is not pointing to the scratch space).
    function verifyMultiProof(
        bytes32[] memory proof,
        bytes32 root,
        bytes32[] memory leaves,
        bool[] memory flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // Cache the lengths of the arrays.
            let leavesLength := mload(leaves)
            let proofLength := mload(proof)
            let flagsLength := mload(flags)

            // Advance the pointers of the arrays to point to the data.
            leaves := add(0x20, leaves)
            proof := add(0x20, proof)
            flags := add(0x20, flags)

            // If the number of flags is correct.
            for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flagsLength) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof, shl(5, proofLength))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                leavesLength := shl(5, leavesLength)
                for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
                    mstore(add(hashesFront, i), mload(add(leaves, i)))
                }
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, leavesLength)
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flagsLength := add(hashesBack, shl(5, flagsLength))

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(mload(flags)) {
                        // Loads the next proof.
                        b := mload(proof)
                        proof := add(proof, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag.
                    flags := add(flags, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flagsLength)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof)
                    )
                break
            }
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The calldata offset of `proof` must be non-zero
    ///   (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
    function verifyMultiProofCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32[] calldata leaves,
        bool[] calldata flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // If the number of flags is correct.
            for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flags.length) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    // forgefmt: disable-next-item
                    isValid := eq(
                        calldataload(
                            xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
                        ),
                        root
                    )
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof.offset, shl(5, proof.length))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, shl(5, leaves.length))
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flags.length := add(hashesBack, shl(5, flags.length))

                // We don't need to make a copy of `proof.offset` or `flags.offset`,
                // as they are pass-by-value (this trick may not always save gas).

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(calldataload(flags.offset)) {
                        // Loads the next proof.
                        b := calldataload(proof.offset)
                        proof.offset := add(proof.offset, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag offset.
                    flags.offset := add(flags.offset, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flags.length)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof.offset)
                    )
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes32 array.
    function emptyProof() internal pure returns (bytes32[] calldata proof) {
        /// @solidity memory-safe-assembly
        assembly {
            proof.length := 0
        }
    }

    /// @dev Returns an empty calldata bytes32 array.
    function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
        /// @solidity memory-safe-assembly
        assembly {
            leaves.length := 0
        }
    }

    /// @dev Returns an empty calldata bool array.
    function emptyFlags() internal pure returns (bool[] calldata flags) {
        /// @solidity memory-safe-assembly
        assembly {
            flags.length := 0
        }
    }
}

// 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: 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);
}

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":"bytes32","name":"_merkleRootA","type":"bytes32"},{"internalType":"bytes32","name":"_merkleRootB","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimedA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimedB","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":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address[]","name":"giftRecipients","type":"address[]"},{"internalType":"uint256","name":"giftAmount","type":"uint256"}],"name":"claimA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address[]","name":"giftRecipients","type":"address[]"},{"internalType":"uint256","name":"giftAmount","type":"uint256"}],"name":"claimB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"claimedA","outputs":[{"internalType":"bool","name":"hasClaimedA","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"claimedB","outputs":[{"internalType":"bool","name":"hasClaimedB","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"isAllowed","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"functionSignature","type":"bytes4"}],"name":"isOpen","outputs":[{"internalType":"bool","name":"canBeCalled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRootA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRootB","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"bool","name":"toggle","type":"bool"}],"name":"toggleContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"internalType":"bool","name":"toggle","type":"bool"}],"name":"toggleFunction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"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"}]

0x610100604052600660c08181526511949251539160d21b60e05262000025908262000187565b5060408051808201909152600681526511949251539160d21b602082015260079062000052908262000187565b506008805460ff191660121790553480156200006d57600080fd5b5060405162001a4138038062001a41833981016040819052620000909162000253565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060809190915260a05262000278565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200010b57607f821691505b6020821081036200012c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000182576000816000526020600020601f850160051c810160208610156200015d5750805b601f850160051c820191505b818110156200017e5782815560010162000169565b5050505b505050565b81516001600160401b03811115620001a357620001a3620000e0565b620001bb81620001b48454620000f6565b8462000132565b602080601f831160018114620001f35760008415620001da5750858301515b600019600386901b1c1916600185901b1785556200017e565b600085815260208120601f198616915b82811015620002245788860151825594840194600190910190840162000203565b5085821015620002435787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600080604083850312156200026757600080fd5b505080516020909101519092909150565b60805160a051611795620002ac600039600081816103c2015261073901526000818161034d0152610e7001526117956000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c8063982d364d116100d8578063d5491e5c1161008c578063e5d54fc011610066578063e5d54fc0146103bd578063f2fde38b146103e4578063f3c73ffe146103f757600080fd5b8063d5491e5c14610348578063dd62ed3e1461036f578063e230ffac1461039a57600080fd5b80639d194d18116100bd5780639d194d18146102ff578063a9059cbb14610312578063babcc5391461032557600080fd5b8063982d364d146102a957806399704063146102dc57600080fd5b8063313ce5671161013a5780638da5cb5b116101145780638da5cb5b1461024957806393ee54a81461028e57806395d89b41146102a157600080fd5b8063313ce567146101f757806340c10f191461021657806370a082311461022957600080fd5b806318160ddd1161016b57806318160ddd146101ba5780631c71f9bc146101d157806323b872dd146101e457600080fd5b806306fdde0314610187578063095ea7b3146101a5575b600080fd5b61018f61040a565b60405161019c91906113a9565b60405180910390f35b6101b86101b336600461143f565b610498565b005b6101c360055481565b60405190815260200161019c565b6101b86101df3660046114b5565b6105bf565b6101b86101f236600461154b565b61092c565b6008546102049060ff1681565b60405160ff909116815260200161019c565b6101b861022436600461143f565b610b20565b6101c3610237366004611587565b60016020526000908152604090205481565b6000546102699073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b6101b861029c3660046115b9565b610c12565b61018f610ce9565b6102cc6102b736600461161c565b600a6020526000908152604090205460ff1681565b604051901515815260200161019c565b6102cc6102ea366004611587565b60046020526000908152604090205460ff1681565b6101b861030d3660046114b5565b610cf6565b6101b861032036600461143f565b611063565b6102cc610333366004611587565b60096020526000908152604090205460ff1681565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6101c361037d366004611637565b600260209081526000928352604080842090915290825290205481565b6102cc6103a8366004611587565b60036020526000908152604090205460ff1681565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6101b86103f2366004611587565b61119b565b6101b8610405366004611661565b61128c565b600680546104179061167d565b80601f01602080910402602001604051908101604052809291908181526020018280546104439061167d565b80156104905780601f1061046557610100808354040283529160200191610490565b820191906000526020600020905b81548152906001019060200180831161047357829003601f168201915b505050505081565b3360009081526009602052604090205460ff16806104e75750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b610552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c495354000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff871680855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35050565b3360009081526004602052604090205460ff1615610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f506f696e74733a20616c726561647920636c61696d65640000000000000000006044820152606401610549565b838111156106c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f506f696e74733a206769667420616d6f756e74206578636565647320636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610549565b60408051336020820152908101859052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301520160405160208183030381529060405280519060200120905061075e88887f00000000000000000000000000000000000000000000000000000000000000008461136f565b6107c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f506f696e74733a20696e76616c69642070726f6f6600000000000000000000006044820152606401610549565b33600090815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581156108ac57600061080e84846116ff565b905061081a838761173a565b955060005b848110156108a957816001600088888581811061083e5761083e611753565b90506020020160208101906108539190611587565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461089c9190611782565b909155505060010161081f565b50505b6108b68286611782565b600560008282546108c79190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff86166000818152600160205260408082208054890190555187929133917fc9fd79e1d8d4b01bc31c31591b73449484b8a2cd1e265129297409b468d56d399190a45050505050505050565b3360009081526009602052604090205460ff168061097b5750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b6109e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c49535400000000000000000000000000000000000000000000006044820152606401610549565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a7557610a43828261173a565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604081208054849290610aaa90849061173a565b909155505073ffffffffffffffffffffffffffffffffffffffff808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610b129086815260200190565b60405180910390a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b8060056000828254610bb39190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600160209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016105b3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600780546104179061167d565b3360009081526003602052604090205460ff1615610d70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f506f696e74733a20616c726561647920636c61696d65640000000000000000006044820152606401610549565b83811115610e00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f506f696e74733a206769667420616d6f756e74206578636565647320636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610549565b60408051336020820152908101859052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610e9588887f00000000000000000000000000000000000000000000000000000000000000008461136f565b610efb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f506f696e74733a20696e76616c69642070726f6f6600000000000000000000006044820152606401610549565b33600090815260036020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558115610fe3576000610f4584846116ff565b9050610f51838761173a565b955060005b84811015610fe0578160016000888885818110610f7557610f75611753565b9050602002016020810190610f8a9190611587565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fd39190611782565b9091555050600101610f56565b50505b610fed8286611782565b60056000828254610ffe9190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff86166000818152600160205260408082208054890190555187929133917f9e530c1f4e73e1ae05ad4b0464ea7f76054a087e37490636b79173927d7044169190a45050505050505050565b3360009081526009602052604090205460ff16806110b25750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b611118576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c49535400000000000000000000000000000000000000000000006044820152606401610549565b336000908152600160205260408120805483929061113790849061173a565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260016020526040908190208054840190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906105b39085815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461121c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461130d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b7fffffffff00000000000000000000000000000000000000000000000000000000919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600083156113a1578360051b8501855b803580851160051b9485526020948518526040600020930181811061137f5750505b501492915050565b60006020808352835180602085015260005b818110156113d7578581018301518582016040015282016113bb565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461143a57600080fd5b919050565b6000806040838503121561145257600080fd5b61145b83611416565b946020939093013593505050565b60008083601f84011261147b57600080fd5b50813567ffffffffffffffff81111561149357600080fd5b6020830191508360208260051b85010111156114ae57600080fd5b9250929050565b600080600080600080600060a0888a0312156114d057600080fd5b873567ffffffffffffffff808211156114e857600080fd5b6114f48b838c01611469565b909950975087915061150860208b01611416565b965060408a0135955060608a013591508082111561152557600080fd5b506115328a828b01611469565b989b979a50959894979596608090950135949350505050565b60008060006060848603121561156057600080fd5b61156984611416565b925061157760208501611416565b9150604084013590509250925092565b60006020828403121561159957600080fd5b6115a282611416565b9392505050565b8035801515811461143a57600080fd5b600080604083850312156115cc57600080fd5b6115d583611416565b91506115e3602084016115a9565b90509250929050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461143a57600080fd5b60006020828403121561162e57600080fd5b6115a2826115ec565b6000806040838503121561164a57600080fd5b61165383611416565b91506115e360208401611416565b6000806040838503121561167457600080fd5b6115d5836115ec565b600181811c9082168061169157607f821691505b6020821081036116ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611735577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561174d5761174d6116d0565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8082018082111561174d5761174d6116d0563b451926ca3bf79ef43e96709171401da10ae54406412ed3ea67469c44d54a0979899e2485ed85b0e0764cff00b772b58e77fa42c300701f8f0714bf8deb5f10

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101825760003560e01c8063982d364d116100d8578063d5491e5c1161008c578063e5d54fc011610066578063e5d54fc0146103bd578063f2fde38b146103e4578063f3c73ffe146103f757600080fd5b8063d5491e5c14610348578063dd62ed3e1461036f578063e230ffac1461039a57600080fd5b80639d194d18116100bd5780639d194d18146102ff578063a9059cbb14610312578063babcc5391461032557600080fd5b8063982d364d146102a957806399704063146102dc57600080fd5b8063313ce5671161013a5780638da5cb5b116101145780638da5cb5b1461024957806393ee54a81461028e57806395d89b41146102a157600080fd5b8063313ce567146101f757806340c10f191461021657806370a082311461022957600080fd5b806318160ddd1161016b57806318160ddd146101ba5780631c71f9bc146101d157806323b872dd146101e457600080fd5b806306fdde0314610187578063095ea7b3146101a5575b600080fd5b61018f61040a565b60405161019c91906113a9565b60405180910390f35b6101b86101b336600461143f565b610498565b005b6101c360055481565b60405190815260200161019c565b6101b86101df3660046114b5565b6105bf565b6101b86101f236600461154b565b61092c565b6008546102049060ff1681565b60405160ff909116815260200161019c565b6101b861022436600461143f565b610b20565b6101c3610237366004611587565b60016020526000908152604090205481565b6000546102699073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b6101b861029c3660046115b9565b610c12565b61018f610ce9565b6102cc6102b736600461161c565b600a6020526000908152604090205460ff1681565b604051901515815260200161019c565b6102cc6102ea366004611587565b60046020526000908152604090205460ff1681565b6101b861030d3660046114b5565b610cf6565b6101b861032036600461143f565b611063565b6102cc610333366004611587565b60096020526000908152604090205460ff1681565b6101c37f3b451926ca3bf79ef43e96709171401da10ae54406412ed3ea67469c44d54a0981565b6101c361037d366004611637565b600260209081526000928352604080842090915290825290205481565b6102cc6103a8366004611587565b60036020526000908152604090205460ff1681565b6101c37f79899e2485ed85b0e0764cff00b772b58e77fa42c300701f8f0714bf8deb5f1081565b6101b86103f2366004611587565b61119b565b6101b8610405366004611661565b61128c565b600680546104179061167d565b80601f01602080910402602001604051908101604052809291908181526020018280546104439061167d565b80156104905780601f1061046557610100808354040283529160200191610490565b820191906000526020600020905b81548152906001019060200180831161047357829003601f168201915b505050505081565b3360009081526009602052604090205460ff16806104e75750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b610552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c495354000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff871680855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35050565b3360009081526004602052604090205460ff1615610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f506f696e74733a20616c726561647920636c61696d65640000000000000000006044820152606401610549565b838111156106c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f506f696e74733a206769667420616d6f756e74206578636565647320636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610549565b60408051336020820152908101859052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301520160405160208183030381529060405280519060200120905061075e88887f79899e2485ed85b0e0764cff00b772b58e77fa42c300701f8f0714bf8deb5f108461136f565b6107c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f506f696e74733a20696e76616c69642070726f6f6600000000000000000000006044820152606401610549565b33600090815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581156108ac57600061080e84846116ff565b905061081a838761173a565b955060005b848110156108a957816001600088888581811061083e5761083e611753565b90506020020160208101906108539190611587565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461089c9190611782565b909155505060010161081f565b50505b6108b68286611782565b600560008282546108c79190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff86166000818152600160205260408082208054890190555187929133917fc9fd79e1d8d4b01bc31c31591b73449484b8a2cd1e265129297409b468d56d399190a45050505050505050565b3360009081526009602052604090205460ff168061097b5750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b6109e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c49535400000000000000000000000000000000000000000000006044820152606401610549565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a7557610a43828261173a565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604081208054849290610aaa90849061173a565b909155505073ffffffffffffffffffffffffffffffffffffffff808416600081815260016020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610b129086815260200190565b60405180910390a350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b8060056000828254610bb39190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600160209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016105b3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600780546104179061167d565b3360009081526003602052604090205460ff1615610d70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f506f696e74733a20616c726561647920636c61696d65640000000000000000006044820152606401610549565b83811115610e00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f506f696e74733a206769667420616d6f756e74206578636565647320636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610549565b60408051336020820152908101859052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610e9588887f3b451926ca3bf79ef43e96709171401da10ae54406412ed3ea67469c44d54a098461136f565b610efb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f506f696e74733a20696e76616c69642070726f6f6600000000000000000000006044820152606401610549565b33600090815260036020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558115610fe3576000610f4584846116ff565b9050610f51838761173a565b955060005b84811015610fe0578160016000888885818110610f7557610f75611753565b9050602002016020810190610f8a9190611587565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fd39190611782565b9091555050600101610f56565b50505b610fed8286611782565b60056000828254610ffe9190611782565b909155505073ffffffffffffffffffffffffffffffffffffffff86166000818152600160205260408082208054890190555187929133917f9e530c1f4e73e1ae05ad4b0464ea7f76054a087e37490636b79173927d7044169190a45050505050505050565b3360009081526009602052604090205460ff16806110b25750600080357fffffffff00000000000000000000000000000000000000000000000000000000168152600a602052604090205460ff165b611118576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f57484954454c49535400000000000000000000000000000000000000000000006044820152606401610549565b336000908152600160205260408120805483929061113790849061173a565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260016020526040908190208054840190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906105b39085815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461121c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60005473ffffffffffffffffffffffffffffffffffffffff16331461130d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610549565b7fffffffff00000000000000000000000000000000000000000000000000000000919091166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600083156113a1578360051b8501855b803580851160051b9485526020948518526040600020930181811061137f5750505b501492915050565b60006020808352835180602085015260005b818110156113d7578581018301518582016040015282016113bb565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461143a57600080fd5b919050565b6000806040838503121561145257600080fd5b61145b83611416565b946020939093013593505050565b60008083601f84011261147b57600080fd5b50813567ffffffffffffffff81111561149357600080fd5b6020830191508360208260051b85010111156114ae57600080fd5b9250929050565b600080600080600080600060a0888a0312156114d057600080fd5b873567ffffffffffffffff808211156114e857600080fd5b6114f48b838c01611469565b909950975087915061150860208b01611416565b965060408a0135955060608a013591508082111561152557600080fd5b506115328a828b01611469565b989b979a50959894979596608090950135949350505050565b60008060006060848603121561156057600080fd5b61156984611416565b925061157760208501611416565b9150604084013590509250925092565b60006020828403121561159957600080fd5b6115a282611416565b9392505050565b8035801515811461143a57600080fd5b600080604083850312156115cc57600080fd5b6115d583611416565b91506115e3602084016115a9565b90509250929050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461143a57600080fd5b60006020828403121561162e57600080fd5b6115a2826115ec565b6000806040838503121561164a57600080fd5b61165383611416565b91506115e360208401611416565b6000806040838503121561167457600080fd5b6115d5836115ec565b600181811c9082168061169157607f821691505b6020821081036116ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611735577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561174d5761174d6116d0565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8082018082111561174d5761174d6116d056

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.