giveaway-skills

Call guide and best practices for the BSC on-chain giveaway contract based on contracts/contracts/Giveaway.sol, including contract address, core method signatures, parameter meanings, and conventions for calling the contract from scripts, frontends, or OpenClow workflows via ethers/web3. Use this skill when you need to create giveaways, claim giveaways, manage whitelists, or withdraw expired giveaways on BSC.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "giveaway-skills" with this command: npx skills add FranckStone/giveaway-skills

BSC Giveaway Contract Call Skill

1. Deployment information

  • Network: BSC (Binance Smart Chain mainnet, chainId = 56)
  • Contract file: contracts/contracts/Giveaway.sol
  • Contract address: 0xc9Db158004fEFe15633eF2Ac3C3eA209e58Db5B9
  • Main dependencies: IERC20, Ownable, ReentrancyGuard, internal TransferHelper library

Assumptions when calling:

  • You are already connected to a BSC mainnet RPC (for example https://bsc-dataseed.binance.org)
  • Account balance and gas settings are handled by the caller

2. Core enums and structs (pass as uint in calls)

DistributionType

  • 0 = AVERAGE: equal share, each claim gets amount / count
  • 1 = RANDOM: random share, a single claim is roughly in the range (0 \sim 2 \times) the average

ClaimRestriction

  • 0 = PUBLIC: public, no additional restriction
  • 1 = TOKEN_HOLDER: only addresses holding restrictionToken with balance ≥ minTokenBalance
  • 2 = WHITELIST: only whitelisted addresses can claim

GiveawayInfo

  • token: token address for the giveaway, address(0) means BNB
  • sender: creator address
  • amount: current remaining total giveaway amount in the contract (after creation fee is deducted)
  • count: current remaining claimable slots
  • distributionType: distribution type (0/1)
  • restriction: claim restriction type (0/1/2)
  • restrictionToken: restriction token address (only meaningful for TOKEN_HOLDER)
  • minTokenBalance: minimum token balance required
  • lastDate: expiration timestamp (seconds)

3. Write function cheatsheet

3.1 Create giveaway createGiveaway

Signature:

function createGiveaway(
    address token,
    uint256 amount,
    uint256 count,
    DistributionType distributionType,
    ClaimRestriction restriction,
    address restrictionToken,
    uint256 minTokenBalance,
    string memory content,
    uint256 lastDate
) public payable

Key constraints:

  • bytes(content).length < 128
  • amount > 0
  • amount / count > 0
  • distributionType ∈ {0,1}
  • restriction ∈ {0,1,2}
  • If restriction == TOKEN_HOLDER (1):
    • restrictionToken != address(0)
    • minTokenBalance > 0

Fees and transfers:

  • Fee: feeAmount = (amount / 1000) * FEERATE, sent directly to FEEADDRESS
  • Actual amount entering the contract: sendAmount = amount - feeAmount
  • If token == address(0) (BNB giveaway):
    • Transaction msg.value >= amount
    • feeAmount and sendAmount are both paid in BNB
  • If token != address(0) (ERC20 giveaway):
    • Transaction msg.value == 0
    • You must first approve on-chain:
      • approve(contract, amount) (user → contract)
    • The contract internally uses safeTransferFrom to send feeAmount to FEEADDRESS and sendAmount to the contract itself

3.2 Claim giveaway claimGiveaway

function claimGiveaway(uint256 id) public nonReentrant

Internal checks:

  • giveawayInfos[id].amount != 0: giveaway exists and has remaining amount
  • Caller has not claimed yet: giveawayInfo_exist[id][msg.sender] == 0
  • Not expired: giveawayInfos[id].lastDate > block.timestamp
  • TOKEN_HOLDER: check IERC20(restrictionToken).balanceOf(msg.sender) >= minTokenBalance
  • WHITELIST: giveawayWhitelist[id][msg.sender] == true

Distribution logic:

  • AVERAGE:
    • If count == 1: send all remaining amount to the current claimer
    • Otherwise, single claim amount is sendAmount = amount / count
  • RANDOM:
    • If count == 1: also send all remaining amount
    • Otherwise:
      • randomNumber = uint8(keccak256(...)) % 100
      • sendAmount = (amount / count * 2) * randomNumber / 100

3.3 Withdraw expired giveaway withdrawExpiredGiveaway

function withdrawExpiredGiveaway(uint256 id) public nonReentrant

Constraints:

  • giveawayInfos[id].amount != 0
  • giveawayInfos[id].sender == msg.sender
  • giveawayInfos[id].lastDate < block.timestamp

Withdrawal fee:

  • feeAmount = (amount / 1000) * EXPIREDRATE
  • sendAmount = amount - feeAmount
  • Transfer logic also distinguishes BNB vs ERC20

3.4 Whitelist management

function addToWhitelist(uint256 giveawayId, address[] memory addresses) public
function removeFromWhitelist(uint256 giveawayId, address[] memory addresses) public

Constraints:

  • Only the giveaway creator: giveawayInfos[giveawayId].sender == msg.sender
  • And the giveaway must be of WHITELIST type: restriction == ClaimRestriction.WHITELIST

4. Read function cheatsheet

function getGiveawayInfo(uint256 id) external view returns (GiveawayInfo memory)
function isInWhitelist(uint256 giveawayId, address user) external view returns (bool)
function canClaim(uint256 id, address user) external view returns (bool)

Key points of canClaim:

  • Returns false if amount is 0, already claimed, or block.timestamp >= lastDate
  • TOKEN_HOLDER: checks token balance
  • WHITELIST: checks whitelist
  • Otherwise returns true (PUBLIC)

5. Script / frontend usage example (ethers.js)

Assume you already have a provider / signer and have loaded the compiled ABI:

import { ethers } from "ethers";
import GiveawayAbi from "../artifacts/contracts/Giveaway.sol/Giveaway.json";

const GIVEAWAY_ADDRESS = "0xc9Db158004fEFe15633eF2Ac3C3eA209e58Db5B9";

// Create contract instance (read or write)
export function getGiveawayContract(providerOrSigner: ethers.Signer | ethers.providers.Provider) {
  return new ethers.Contract(GIVEAWAY_ADDRESS, GiveawayAbi.abi, providerOrSigner);
}

// Example: create a BNB giveaway
export async function createBnbGiveaway(
  signer: ethers.Signer,
  params: {
    amountWei: ethers.BigNumberish;
    count: number;
    distributionType: 0 | 1;
    restriction: 0 | 1 | 2;
    restrictionToken: string;
    minTokenBalance: ethers.BigNumberish;
    content: string;
    lastDate: number;
  }
) {
  const contract = getGiveawayContract(signer);
  const tx = await contract.createGiveaway(
    ethers.constants.AddressZero,
    params.amountWei,
    params.count,
    params.distributionType,
    params.restriction,
    params.restrictionToken,
    params.minTokenBalance,
    params.content,
    params.lastDate,
    { value: params.amountWei }
  );
  return tx.wait();
}

// Example: claim a giveaway
export async function claimGiveaway(signer: ethers.Signer, id: number) {
  const contract = getGiveawayContract(signer);
  const tx = await contract.claimGiveaway(id);
  return tx.wait();
}

When integrating in a frontend or script:

  • Read functions (getGiveawayInfo, canClaim, isInWhitelist) can use a provider instance;
  • Write functions (createGiveaway, claimGiveaway, withdrawExpiredGiveaway, whitelist add/remove) must use a signer with signing capability;
  • For BNB giveaways you must pass BNB equal to amount via value; for ERC20 giveaways you must approve beforehand.

7. ABI information and minimal examples

  • Full ABI source: the JSON generated after compiling contracts/contracts/Giveaway.sol in this repo (for example artifacts/.../Giveaway.json); in scripts/frontends you should generally import the abi field from that file.
  • Purpose of this section: provide a minimal ABI fragment for quick debugging or building a minimal frontend/script when you cannot directly access the compiled artifacts. It is not guaranteed to stay perfectly in sync with future contract upgrades.

7.1 Key event fragments

[
  {
    "type": "event",
    "name": "GiveawayCreated",
    "anonymous": false,
    "inputs": [
      { "indexed": false, "name": "id", "type": "uint256" },
      { "indexed": false, "name": "token", "type": "address" },
      { "indexed": false, "name": "sender", "type": "address" },
      { "indexed": false, "name": "amount", "type": "uint256" },
      { "indexed": false, "name": "count", "type": "uint256" },
      { "indexed": false, "name": "distributionType", "type": "uint8" },
      { "indexed": false, "name": "restriction", "type": "uint8" },
      { "indexed": false, "name": "restrictionToken", "type": "address" },
      { "indexed": false, "name": "minTokenBalance", "type": "uint256" },
      { "indexed": false, "name": "content", "type": "string" },
      { "indexed": false, "name": "lastDate", "type": "uint256" }
    ]
  },
  {
    "type": "event",
    "name": "GiveawayClaimed",
    "anonymous": false,
    "inputs": [
      { "indexed": false, "name": "id", "type": "uint256" },
      { "indexed": false, "name": "sender", "type": "address" },
      { "indexed": false, "name": "count", "type": "uint256" },
      { "indexed": false, "name": "amount", "type": "uint256" }
    ]
  },
  {
    "type": "event",
    "name": "GiveawayWithdrawn",
    "anonymous": false,
    "inputs": [
      { "indexed": false, "name": "id", "type": "uint256" }
    ]
  },
  {
    "type": "event",
    "name": "WhitelistAdded",
    "anonymous": false,
    "inputs": [
      { "indexed": true, "name": "giveawayId", "type": "uint256" },
      { "indexed": false, "name": "addresses", "type": "address[]" }
    ]
  },
  {
    "type": "event",
    "name": "WhitelistRemoved",
    "anonymous": false,
    "inputs": [
      { "indexed": true, "name": "giveawayId", "type": "uint256" },
      { "indexed": false, "name": "addresses", "type": "address[]" }
    ]
  }
]

7.2 Common function fragments

Only the most common read/write function signatures are listed below, to make it easy to construct ethers.Contract / web3.eth.Contract. For the full ABI, always refer to the build artifacts.

[
  {
    "type": "function",
    "stateMutability": "payable",
    "name": "createGiveaway",
    "inputs": [
      { "name": "token", "type": "address" },
      { "name": "amount", "type": "uint256" },
      { "name": "count", "type": "uint256" },
      { "name": "distributionType", "type": "uint8" },
      { "name": "restriction", "type": "uint8" },
      { "name": "restrictionToken", "type": "address" },
      { "name": "minTokenBalance", "type": "uint256" },
      { "name": "content", "type": "string" },
      { "name": "lastDate", "type": "uint256" }
    ],
    "outputs": []
  },
  {
    "type": "function",
    "stateMutability": "nonpayable",
    "name": "claimGiveaway",
    "inputs": [
      { "name": "id", "type": "uint256" }
    ],
    "outputs": []
  },
  {
    "type": "function",
    "stateMutability": "nonpayable",
    "name": "withdrawExpiredGiveaway",
    "inputs": [
      { "name": "id", "type": "uint256" }
    ],
    "outputs": []
  },
  {
    "type": "function",
    "stateMutability": "nonpayable",
    "name": "addToWhitelist",
    "inputs": [
      { "name": "giveawayId", "type": "uint256" },
      { "name": "addresses", "type": "address[]" }
    ],
    "outputs": []
  },
  {
    "type": "function",
    "stateMutability": "nonpayable",
    "name": "removeFromWhitelist",
    "inputs": [
      { "name": "giveawayId", "type": "uint256" },
      { "name": "addresses", "type": "address[]" }
    ],
    "outputs": []
  },
  {
    "type": "function",
    "stateMutability": "view",
    "name": "getGiveawayInfo",
    "inputs": [
      { "name": "id", "type": "uint256" }
    ],
    "outputs": [
      {
        "components": [
          { "name": "token", "type": "address" },
          { "name": "sender", "type": "address" },
          { "name": "amount", "type": "uint256" },
          { "name": "count", "type": "uint256" },
          { "name": "distributionType", "type": "uint8" },
          { "name": "restriction", "type": "uint8" },
          { "name": "restrictionToken", "type": "address" },
          { "name": "minTokenBalance", "type": "uint256" },
          { "name": "lastDate", "type": "uint256" }
        ],
        "type": "tuple"
      }
    ]
  },
  {
    "type": "function",
    "stateMutability": "view",
    "name": "canClaim",
    "inputs": [
      { "name": "id", "type": "uint256" },
      { "name": "user", "type": "address" }
    ],
    "outputs": [
      { "type": "bool" }
    ]
  },
  {
    "type": "function",
    "stateMutability": "view",
    "name": "isInWhitelist",
    "inputs": [
      { "name": "giveawayId", "type": "uint256" },
      { "name": "user", "type": "address" }
    ],
    "outputs": [
      { "type": "bool" }
    ]
  }
]

The fragments above can be combined with the TypeScript example earlier, for example:

const abi = [...eventsFragment, ...functionsFragment];
const contract = new ethers.Contract(GIVEAWAY_ADDRESS, abi, signerOrProvider);

6. Relationship with existing giveaway-protocol skill

  • giveaway-protocol focuses more on the protocol-level description (enum semantics, logical constraints, general call conventions);
  • giveaway-skills is specifically about this concrete contract deployed on BSC mainnet (fixed contract address + specific network info + call examples).

When you need “the contract address and direct on-chain interaction”, you should prefer this skill.
If you need more complete error descriptions or protocol details, you can also refer to giveaway-protocol’s reference.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Web3

End-to-end encrypted messaging and EVM crypto wallet for agent identity

End-to-end encrypted messaging for AI agents. Register unique usernames and send cryptographically private messages with blinded inboxes. Create encrypted group chats with Sender Keys protocol. Set your profile with username, description, public key and EVM crypto address. Search for other AI agents based on their usernames and descriptions. Also supports multi-chain crypto transfers (ETH, Base, BSC) to @username.

Registry SourceRecently Updated
21.9K
Profile unavailable
Web3

Bsc Dev Monitor Skill

BSC Dev Wallet Monitor - 专为跟投 Dev 的用户设计。 监控指定 BSC 地址的代币转出(发币)行为,第一时间发现新币发布。 支持 Webhook 通知、安全检测、历史记录等功能。

Registry SourceRecently Updated
0143
Profile unavailable
Web3

Bsc Dev Monitor Skill

BSC Dev Wallet Monitor - 专为跟投 Dev 的用户设计。 监控指定 BSC 地址的代币转出(发币)行为,第一时间发现新币发布。 支持 Webhook 通知、安全检测、历史记录等功能。

Registry SourceRecently Updated
0126
Profile unavailable