$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:
- How to create token drops of NEAR, FTs, and NFTs
- How to use Function Call keys to let someone claim tokens without signing in to the funder’s account
Contract Overview
The contract exposescreate_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:
- Alice calls
create_dropwith a NEAR amount and one or more public keys, attaching enough NEAR to fund the drop and its costs. - The contract records the drop and adds the public keys to its own account as FunctionCall keys that can only call
claim_for. - Alice gives a corresponding private key to Bob.
- Bob uses that key to sign a transaction as the drop contract’s account, calling
claim_forwith his existing account ID. - The contract consumes the key and transfers the drop to Bob.
Contract's interface
Contract's interface
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 aDropId, which identifies a drop. Its state contains:
next_drop_id: A counter used to assign identifiers to new dropsdrop_by_id: A map from eachDropIdto its drop datadrop_id_by_key: A map from each public key to the drop it can claimkeys_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
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
- FT Drop
- NFT 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
claim_for:
lib.rs
Storage Costs
Before creating a drop, callget_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 asreceiver_idand the returneddrop_idencoded as a string inmsg. Transfer exactlyamount_per_dropmultiplied 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 asaccount_idand the returneddrop_idencoded as a string inmsg. Attach the approval storage deposit required by the NFT contract. The NFT remains with the funder until claimed.
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 toclaim_for.
claim.rs
claim.rs
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 calldelete_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: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 withnew, which takes an empty JSON object:
CLI: Interacting with the Contract
Quote and Create a Drop
Save a drop input indrop-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:
drop-cost-args.json and add a top-level funder field containing the account that will create the drop:
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 returneddrop_id: