Skip to main content
NEAR Drop is a smart contract that allows users to create token drops ($NEAR, Fungible and Non-Fungible Tokens), and link them to specific private keys. Whoever has a private key can claim its drop into an existing account. Particularly, it shows:
  1. How to create token drops of NEAR, FTs, and NFTs
  2. How to use Function Call keys to let someone claim tokens without signing in to the funder’s account
The example repository contains the contract and its tests.

Contract Overview

The contract exposes create_drop to create a NEAR, FT, or NFT drop, and claim_for to claim it into an existing account. It uses FunctionCall keys on the contract’s own account to authorize claims. Imagine Alice wants to drop some NEAR to Bob:
  1. Alice calls create_drop with a NEAR amount and one or more public keys, attaching enough NEAR to fund the drop and its costs.
  2. The contract records the drop and adds the public keys to its own account as FunctionCall keys that can only call claim_for.
  3. Alice gives a corresponding private key to Bob.
  4. Bob uses that key to sign a transaction as the drop contract’s account, calling claim_for with his existing account ID.
  5. The contract consumes the key and transfers the drop to Bob.
The key authorizes a claim on the contract’s account. It does not give Bob full access to that account or to Alice’s account.

create_drop(drop)

Creates a drop from a NEAR, FT, or NFT input and returns its drop_id. The caller becomes the funder.

get_drop_cost(funder, drop)

Quotes the NEAR deposit needed to create a drop for the given funder and input.

claim_for(account_id)

Claims a drop into an existing account, using its FunctionCall key.

delete_drop(drop_id)

Lets the funder cancel the remaining keys and request refunds for unused assets and budgets.

get_drop_by_id(drop_id) and get_drop_id_by_key(public_key)

Return the stored drop or the drop ID associated with a public key.

Contract’s State

The contract links each public key to a DropId, which identifies a drop. Its state contains:
  • next_drop_id: A counter used to assign identifiers to new drops
  • drop_by_id: A map from each DropId to its drop data
  • drop_id_by_key: A map from each public key to the drop it can claim
  • keys_by_drop: The remaining public keys for each drop, used when claiming or deleting it
lib.rs

Drop Types

There are three types of drops, which differ in what the recipient receives. CreateDrop defines their inputs:
drop_types.rs
NEAR and FT drops can have multiple public keys, each receiving amount_per_drop. A NEAR amount is expressed in yoctoNEAR; an FT amount is expressed in that token’s smallest units. An NFT drop has one public key and identifies the NFT contract. Its token ID is recorded when the funder approves the NFT for the drop.
near_drop.rs
Each drop contains one type of asset. To distribute a mixture of NEAR, FTs, and NFTs, create separate drops.

Create a drop

create_drop builds the requested drop, checks that its keys are available, saves the drop, and charges for storage and the per-key budgets. Keys must be unique, and a key already associated with a drop cannot be reused.
lib.rs
The contract adds the supplied keys to its own account with permission to call only claim_for:
lib.rs

Storage Costs

Before creating a drop, call get_drop_cost with the creator’s account as funder and the same drop input you will pass to create_drop. The quote is returned in yoctoNEAR as a JSON string. The deposit covers the stored drop, its key mappings, access-key storage, and a gas contribution for each claim. NEAR drops also include the tokens being distributed. FT drops include a recipient-registration budget, while NFT drops reserve space for the token ID. The contract measures storage during creation and refunds any excess deposit. The per-key gas contribution and the FunctionCall key’s spending allowance serve different purposes. The contract account also needs a liquid NEAR reserve to purchase gas before protocol refunds arrive; that reserve must be maintained separately from storage backing and assets owed to users.

Funding FT and NFT Drops

Creating an FT or NFT drop records its configuration. The funder then supplies or approves the asset:
  • FT: Call the token contract’s ft_transfer_call, with the drop contract as receiver_id and the returned drop_id encoded as a string in msg. Transfer exactly amount_per_drop multiplied by the number of keys, and attach 1 yoctoNEAR. Only the drop’s funder can fund it.
  • NFT: Call the NFT contract’s nft_approve, with the drop contract as account_id and the returned drop_id encoded as a string in msg. Attach the approval storage deposit required by the NFT contract. The NFT remains with the funder until claimed.
An FT claim checks whether the recipient is registered and registers it if necessary. The implementation budgets 0.00126 NEAR for registration. An unneeded registration budget is refunded to the funder; any excess refunded by the FT contract after a new registration remains in the drop contract.

Claim a drop

To claim a drop, sign a transaction as the drop contract’s account using the private key corresponding to one of its FunctionCall keys. Pass an existing recipient account ID to claim_for.
claim.rs
The contract consumes the key before starting the asset transfer. It removes the key’s mapping and requests deletion of the access key. When the last key is consumed, it removes the drop’s stored data; otherwise, it updates the remaining key count.
claim.rs
Read the returned boolean: true means the asset was delivered, while false indicates a handled failure, including an unfunded drop. A successful transaction alone does not establish delivery. Handled failures consume the key and request refunds of unused assets and deposits to the funder. Transaction rejection or a runtime failure can still fail without returning a boolean.

Cancel a Drop

The funder can call delete_drop to cancel its remaining keys. The contract requests deletion of those keys and refunds unused assets, storage, and the remaining keys’ gas and registration budgets. For NFT drops, the funder still owns the NFT and can revoke its approval separately.

Testing the Contract

Clone the repository, navigate to its directory, and run the tests:
The sandbox tests build the drop contract and its FT/NFT fixtures from source, then use near-sandbox and near-api to exercise creation, funding, claiming, deletion, and refunds. Claims are signed with the restricted drop keys. The suite also checks exact deposit quotes, storage reserves, and callback access controls. The gas benchmark is opt-in.

Deploying the Contract to the NEAR network

Create and fund a testnet account using the NEAR CLI, then build and deploy the contract. Initialize it with new, which takes an empty JSON object:

CLI: Interacting with the Contract

Quote and Create a Drop

Save a drop input in drop-args.json, replacing the public keys with keys you generated for the recipients. For example, this input creates two NEAR claims of 0.01 NEAR each:
To quote the cost, copy that input to drop-cost-args.json and add a top-level funder field containing the account that will create the drop:
Record the returned drop_id. For FT and NFT drops, use the corresponding variant in the drop field, quote its cost, create it, and complete the funding or approval step described above.

Claim into an Existing Account

Give each recipient the private key corresponding to their public key. A recipient can claim with 32 TGas and no attached deposit:

Delete a Drop

To cancel a drop, sign as its funder and pass the returned drop_id: