Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"KushlingsClaim.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IERC721 {
function ownerOf(uint256 tokenId) external view returns (address);
function transferFrom(address from, address to, uint256 tokenId) external;
}
library MerkleProof {
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == root;
}
}
abstract contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
require(initialOwner != address(0), "owner=0");
owner = initialOwner;
emit OwnershipTransferred(address(0), initialOwner);
}
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "owner=0");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() { _status = _NOT_ENTERED; }
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
contract KushlingsClaim is Ownable, ReentrancyGuard {
IERC721 public nft;
address public treasury;
uint256 public startId;
uint256 public endId;
uint256 public cursor;
bytes32 public merkleRoot;
bool public paused;
mapping(address => uint256) public claimed;
event Claimed(address indexed to, uint256 indexed tokenId);
event MerkleRootSet(bytes32 newRoot);
error BadRange();
error PausedErr();
error SoldOut();
error NotAllowlisted();
error ExceedsAllowance(uint256 want, uint256 max);
constructor(
address _nft,
address _treasury,
uint256 _startId,
uint256 _endId,
bytes32 _merkleRoot,
address _owner
) Ownable(_owner) {
require(_startId <= _endId, "bad range");
nft = IERC721(_nft);
treasury = _treasury;
startId = _startId;
endId = _endId;
cursor = _startId;
merkleRoot = _merkleRoot;
paused = true;
}
function setPaused(bool _paused) external onlyOwner {
paused = _paused;
}
function setRange(uint256 _startId, uint256 _endId) external onlyOwner {
if (_startId > _endId) revert BadRange();
startId = _startId;
endId = _endId;
if (cursor < _startId) cursor = _startId;
}
function setMerkleRoot(bytes32 _root) external onlyOwner {
merkleRoot = _root;
emit MerkleRootSet(_root);
}
function maxFor(address account, uint256 maxFromLeaf, bytes32[] calldata proof)
public
view
returns (uint256)
{
if (merkleRoot == bytes32(0)) {
return type(uint256).max;
}
bytes32 leaf = keccak256(abi.encodePacked(account, maxFromLeaf));
if (!MerkleProof.verify(proof, merkleRoot, leaf)) revert NotAllowlisted();
return maxFromLeaf;
}
function claim(uint256 qty, uint256 maxFromLeaf, bytes32[] calldata proof)
external
nonReentrant
{
if (paused) revert PausedErr();
require(qty > 0, "qty=0");
uint256 maxAllowed = maxFor(msg.sender, maxFromLeaf, proof);
uint256 newTotal = claimed[msg.sender] + qty;
if (newTotal > maxAllowed) revert ExceedsAllowance(qty, maxAllowed);
uint256 id = cursor;
unchecked {
for (uint256 i = 0; i < qty; i++) {
while (id <= endId && nft.ownerOf(id) != treasury) {
id++;
}
if (id > endId) revert SoldOut();
nft.transferFrom(treasury, msg.sender, id);
emit Claimed(msg.sender, id);
id++;
}
}
cursor = id;
claimed[msg.sender] = newTotal;
}
}
"
}
},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}
}}
Submitted on: 2025-10-31 17:16:37
Comments
Log in to comment.
No comments yet.