尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Paid calls for wildlife sightings, checked on iNaturalist by GenLayer validators who look at the photos
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Paid calls for wildlife sightings. Anyone funds a call; naturalists post on iNaturalist as they always do; GenLayer validators check each sighting, look at the photos when the call asks for something specific, and pay the observer.
Conservation work runs on records: where an invasive hornet is nesting, whether hedgehogs still breed in a town, whether a rare orchid flowered this year. Millions of people already photograph wildlife and post it to iNaturalist, where a community identifies every record. But nobody pays for the one record that matters, and when someone tries (a bounty for nests, a reward for a first county record), every sighting has to be checked by hand and every payout trusted to whoever holds the money.
FieldCall turns that into a contract:
MEETS, NOT_MEETS or UNCLEAR; they must agree. They never re-identify the
species: the iNaturalist community already did.0x… address to their profile and anyone presses Collect.Live app: fieldcall-bars26.vercel.app. Paste any iNaturalist observation and see, without a wallet, which open calls it would earn and why. Writes need MetaMask on GenLayer Studio (chain 61999); Test GEN funds your wallet.
Contract: 0x58576b0a8C0091b8E7E276EDCa9b5D2d9bC826aE on GenLayer Studio.
MEETS, NOT_MEETS, UNCLEAR) so their agreement is strict. Verified on Studio: a nest photo and a photo of an adult
hornet on a branch, from the same observer on the same day, get opposite answers.scripts/demo.mjs opened two demo calls with test wallets and submitted real observations of the yellow-legged (Asian) hornet,
Vespa velutina, which the UK asks the public to report. Every transaction, reason, evidence packet and the balance
reconciliation are in docs/REPRODUCTION.md.
| Call | Observation | Ruling and stored reason |
|---|---|---|
| Asian hornet nests, UK, 0.5 GEN, photo condition "The photo shows a hornet nest" | 397236824: a nest in a tree, Romsey, 2026-08-20 | Qualifies. Validators looked at the photo and it shows a nest. A co-funder's fresh reading confirmed it. The observer has no wallet in their profile, so the reward is held for them |
| same | 397236834: an adult hornet on a branch, same observer, same day | Does not qualify: validators looked at three photos, NOT_MEETS each |
| same | 411158753: a European hornet, the native lookalike | Does not qualify: Vespa crabro is not Vespa velutina (decided in code; the scout's fresh reading agreed) |
| same | 411204951: an Asian hornet in France | Does not qualify: not inside the United Kingdom |
| same | 182971213: Hull, 2023 | Does not qualify: outside the call's dates |
| Asian hornet sightings, UK, 0.25 GEN, 2 per observer | three adults by the same observer | Qualifies, qualifies, then refused: the observer reached the call's limit of 2 |
Also refused on-chain, with the GEN sent back: a taxon name instead of an id, a taxon and a place iNaturalist does not have, a
call that has already ended, a reward below 0.1 GEN, a pot smaller than one reward, a start date of 2026-02-31, and a 0.05 GEN
top-up (below the 0.1 GEN minimum). And refused by the contract: submitting an observation that is already open, already earned
its reward, or was already submitted three times; a scout paying out early (only a funder can); collecting a held reward before
the observer links a wallet; and closing a call before its collect date. The contract's balance was reconciled
with totals() (open pots plus reserved rewards) at three points of the run, each time after every transfer had finalized.
From the live app with MetaMask: a tester opened a third call from the Live hedgehogs, UK preset (photo condition
"The photo shows a living hedgehog") and submitted three real observations: a hedgehog walking on a road qualified
(validators looked: MEETS, reward held for its observer), a dead hedgehog did not (NOT_MEETS), and a live hedgehog
whose observer opened their account two days before the sighting did not (the call requires 30 days; decided in code).
Transactions in docs/REPRODUCTION.md.
| Rule | Why |
|---|---|
The reward goes only to the 0x address in the observer's own iNaturalist profile | Submitting someone else's observation cannot redirect their reward; anyone can submit, nobody can steal |
| Taxonomy is the iNaturalist community's: the observation's identification must be the call's taxon or below it | Validators judge the photo condition only; a lookalike species fails in code, not by opinion |
| Research grade, not captive, inside the place, inside the dates, located precisely enough, account old enough: all in code | Every validator gets the same answer from the same record; no model judgement where a field decides |
| A photo condition is answered per photo with a fixed answer set; the first photo that clearly shows it decides | Strict consensus on an image judgement; a vague photo is UNCLEAR and reserves nothing |
| One payout per observation per call, at most N per observer, and a funder's wallet is never paid by its own call | One prolific account, or the sponsor, cannot drain the pot |
| Only the side a ruling goes against asks for a fresh reading, once each, inside 10 minutes | An identification that changes can still be read; nobody spends the other side's answer |
| Early settlement only against your own interest (a funder pays now, the submitter accepts a refusal) | The submitter cannot rush a payout; funders cannot rush a refusal |
iNaturalist outages, unreadable profiles and photos are UNCLEAR: nothing reserved, submit again | An outage never decides a sighting |
| Held rewards wait until the collect date (call end + 30 days), then return to the pot; the pot returns to funders pro rata | Money never strands; observers who join late still get paid |
Closing does a fixed amount of work; each funder's share is then returned by its own refund transaction, which anyone can send (always to that funder) | No call can grow so large that closing it runs out of gas and strands the funders' GEN |
| Funders, observer counts and submission counts live in their own maps, never in a list on the call; top-ups are at least 0.1 GEN; one observation can be submitted to a call at most 3 times | Spam cannot make any write more expensive than the first one |
Payable calls never revert; they refund and return REFUNDED: <reason>, including for dates that do not exist (2026-02-31) |
get_calls and one get_sightings
call, CDN-cached; iNaturalist is read straight from the browser.pip install -r requirements.txt
genvm-lint check contracts/field_call.py
pytest tests/direct/ -v # 55 tests: iNaturalist, profiles, photos and the LLM mocked
npm install
node scripts/deploy.mjs
node scripts/verify-code.mjs <address>
node scripts/demo.mjs <address> # the live run above (about 30 minutes)
node scripts/reproduction.mjs # regenerate docs/REPRODUCTION.md
cd frontend && cp .env.example .env.local && npm run dev
close() looped over every sighting and every funder in one transaction, and
both lists could be padded cheaply. Now close() only moves the pot and the expired held rewards into returnable; every
funder is then repaid by refund(call_id, funder), one bounded transaction each, sent by anyone, in any order, with the
last one taking the rounding remainder. Funders, per-observer counts and submission counts moved out of the call record into
their own maps, top-ups are at least 0.1 GEN, and an observation can be submitted to a call at most three times.
test_stress_hundreds_of_funders_and_refused_sightings_still_close_and_repay_everyone pads a call with 301 funders and 120
refused submissions, checks that close() reads no sighting and no funder, then repays all 301 and checks every wei left.create_call checks that starts and ends are real calendar dates before any date
arithmetic, so 2026-02-31 returns REFUNDED: ... with the GEN, instead of raising and keeping it; covered by tests that
record every transfer and by the live run.Observations and photos are © their authors on iNaturalist and are shown with their attribution and licence.
MIT licensed.
| GenLayer keeps the value of a reverted call |