Discover more of Apescan's tools and services in one place.
Contract Source Code:
File 1 of 1 : ApeBombNftWinnerClaim.sol
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface INFTShadow { function locked(uint256 tokenId) external view returns (bool); function ownerOf(uint256 tokenId) external view returns (address); } interface IApeBomb { function owner() external view returns (address); } struct Winner { address contractAddress; uint96 amount; uint64 tokenId; uint40 timestamp; bool claimed; bool reclaimed; } contract ApeBombNftWinnerClaim { error NoWinner(); error NotExpired(); error NotApeBombContract(); error InvalidCaller(); error AlreadyClaimed(); error TransferFailed(); error TokenIsLocked(); error NotOwner(); event WinnerSet(uint256 tournamentId, Winner winner); event Claimed(uint256 tournamentId, address winner, uint256 amount); event Reclaimed(uint256 tournamentId, address winner, uint256 amount); mapping(uint256 tournamentId => Winner) public winners; address public immutable APE_BOMB_CONTRACT_ADDRESS; uint256 public constant EXPIRATION = 30 days; constructor(address _apeBombContract) { APE_BOMB_CONTRACT_ADDRESS = _apeBombContract; } /** * @dev Set the winner of the tournament. * @param tournamentId The ID of the tournament. * @param contractAddress The address of the NFT contract. * @param tokenId The ID of the NFT. */ function setWinner(uint256 tournamentId, address contractAddress, uint256 tokenId) external payable { if (msg.sender != APE_BOMB_CONTRACT_ADDRESS) revert NotApeBombContract(); winners[tournamentId] = Winner({ contractAddress: contractAddress, amount: uint96(msg.value), tokenId: uint64(tokenId), timestamp: uint40(block.timestamp), claimed: false, reclaimed: false }); emit WinnerSet(tournamentId, winners[tournamentId]); } /** * @dev Claim the winner's NFT. * @param tournamentId The ID of the tournament. */ function claim(uint256 tournamentId) external { if (winners[tournamentId].amount == 0) revert NoWinner(); INFTShadow nftShadow = INFTShadow(winners[tournamentId].contractAddress); if (winners[tournamentId].claimed || winners[tournamentId].reclaimed) revert AlreadyClaimed(); winners[tournamentId].claimed = true; uint256 tokenId = winners[tournamentId].tokenId; if (nftShadow.locked(tokenId)) revert TokenIsLocked(); if (nftShadow.ownerOf(tokenId) != msg.sender) revert NotOwner(); (bool success,) = payable(msg.sender).call{value: winners[tournamentId].amount}(""); if (!success) revert TransferFailed(); emit Claimed(tournamentId, msg.sender, winners[tournamentId].amount); } /** * @dev If the winner does not claim within 30 days, 90% of the funds will be added to the current ApeBomb tournament * and the remaining 10% will be sent to the ApeBomb owner. * @param tournamentId The ID of the tournament. */ function reclaim(uint256 tournamentId) external { if (winners[tournamentId].amount == 0) revert NoWinner(); if (winners[tournamentId].claimed || winners[tournamentId].reclaimed) revert AlreadyClaimed(); if (block.timestamp < winners[tournamentId].timestamp + EXPIRATION) revert NotExpired(); winners[tournamentId].reclaimed = true; uint256 totalAmount = winners[tournamentId].amount; uint256 amountToTournament = totalAmount * 90 / 100; uint256 amountToOwner = totalAmount - amountToTournament; (bool success,) = payable(APE_BOMB_CONTRACT_ADDRESS).call{value: amountToTournament}(""); if (!success) revert TransferFailed(); (success,) = payable(IApeBomb(APE_BOMB_CONTRACT_ADDRESS).owner()).call{value: amountToOwner}(""); if (!success) revert TransferFailed(); emit Reclaimed(tournamentId, APE_BOMB_CONTRACT_ADDRESS, winners[tournamentId].amount); } }
Please enter a contract address above to load the contract details and source code.
Please DO NOT store any passwords or private keys here. A private note (up to 100 characters) can be saved and is useful for transaction tracking.
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.