feat: add recipient balance filtering to faucet#273
Open
ivegabr wants to merge 2 commits into
Open
Conversation
- Introduced new environment variables: `FILTER_BY_BALANCE` and `MAX_RECEIVER_BALANCE` to control recipient balance checks.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an optional “recipient balance cap” to reduce faucet abuse by rejecting dispenses to addresses whose on-chain balance exceeds a configurable threshold.
Changes:
- Added
FILTER_BY_BALANCEandMAX_RECEIVER_BALANCEconfiguration and documentation. - Implemented recipient balance validation (with promo-code bypass).
- Updated deployment workflows to pass the new env vars.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/validations.ts | Adds receiverBalanceExceeded validation based on configured maximum balance. |
| src/utils/startup-context.ts | Exposes balance-filter settings in startup context logging. |
| src/constants/env.ts | Adds server env parsing for new balance-filter variables. |
| src/app/lib/action.ts | Fetches recipient balance (when enabled) and runs new validation. |
| README.md | Documents new env vars and dispense limit behaviors. |
| .github/workflows/prod-deploy.yml | Passes new env vars into deployment environment generation. |
| .github/workflows/dev-deploy.yml | Passes new env vars into deployment environment generation. |
| .env.example | Adds new env vars to example configuration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+86
to
+89
| const recipientBalanceWei = | ||
| serverEnv.FILTER_BY_BALANCE && !promoCode | ||
| ? BigInt(await web3.eth.getBalance(dispenseAddress)) | ||
| : BigInt(0); |
Comment on lines
+35
to
+40
| const maxBalanceWei = BigInt( | ||
| Web3.utils.toWei(serverEnv.MAX_RECEIVER_BALANCE.toString(), 'ether') | ||
| ); | ||
| if (recipientBalanceWei > maxBalanceWei) { | ||
| return `This address already holds more than ${serverEnv.MAX_RECEIVER_BALANCE} test RBTC and cannot receive more from the faucet.`; | ||
| } |
Comment on lines
25
to
28
| FILTER_BY_IP: process.env.FILTER_BY_IP === 'true', | ||
| FILTER_BY_BALANCE: process.env.FILTER_BY_BALANCE === 'true', | ||
| MAX_RECEIVER_BALANCE: Number(process.env.MAX_RECEIVER_BALANCE ?? '0.1'), | ||
| TIMER_LIMIT: Number(process.env.TIMER_LIMIT), |
Comment on lines
117
to
120
| FILTER_BY_IP: ${{ secrets.FILTER_BY_IP }} | ||
| FILTER_BY_BALANCE: ${{ secrets.FILTER_BY_BALANCE }} | ||
| MAX_RECEIVER_BALANCE: ${{ secrets.MAX_RECEIVER_BALANCE }} | ||
| TIMER_LIMIT: ${{ secrets.TIMER_LIMIT }} |
Comment on lines
124
to
127
| FILTER_BY_IP: ${{ secrets.FILTER_BY_IP }} | ||
| FILTER_BY_BALANCE: ${{ secrets.FILTER_BY_BALANCE }} | ||
| MAX_RECEIVER_BALANCE: ${{ secrets.MAX_RECEIVER_BALANCE }} | ||
| TIMER_LIMIT: ${{ secrets.TIMER_LIMIT }} |
Comment on lines
+3
to
+9
| function parseMaxReceiverBalance(): number { | ||
| const raw = process.env.MAX_RECEIVER_BALANCE ?? String(DEFAULT_MAX_RECEIVER_BALANCE); | ||
| const value = Number(raw); | ||
| if (!Number.isFinite(value) || value < 0) { | ||
| return DEFAULT_MAX_RECEIVER_BALANCE; | ||
| } | ||
| return value; |
| @@ -1,13 +1,16 @@ | |||
| import { ValidationError } from '@/utils/validations'; | |||
Comment on lines
+31
to
33
| filterByBalance: process.env.FILTER_BY_BALANCE === 'true', | ||
| maxReceiverBalance: Number(process.env.MAX_RECEIVER_BALANCE ?? '0.1') || undefined, | ||
| timerLimitMs: Number(process.env.TIMER_LIMIT) || undefined, |
Comment on lines
+264
to
+267
| if (shouldCheckBalance) { | ||
| const recipientBalanceWei = BigInt(await web3.eth.getBalance(dispenseAddress)); | ||
| addOutcome(receiverBalanceExceeded(recipientBalanceWei, promoCode)); | ||
| } |
Comment on lines
+64
to
+66
| | Per IP | `FILTER_BY_IP` | `false` | Rejects if the same IP already requested within `TIMER_LIMIT` | | ||
| | Per address | `TIMER_LIMIT` | `180000` ms (3 min) | Rejects if the recipient address already received tokens within the timer window | | ||
| | Recipient balance | `FILTER_BY_BALANCE`, `MAX_RECEIVER_BALANCE` | disabled, `0.1` RBTC | When enabled, rejects if the recipient already holds `MAX_RECEIVER_BALANCE` tRBTC or more | |
| | Faucet balance | — | — | Rejects if the faucet wallet has less than 0.1 tRBTC | | ||
| | Captcha | — | — | Rejects if reCAPTCHA verification fails | | ||
|
|
||
| `TIMER_LIMIT` applies to the per-address check. The faucet history is also reset daily at midnight (Pacific time). |
| |---|---| | ||
| | Per IP (`FILTER_BY_IP`) | Yes | | ||
| | Recipient balance (`FILTER_BY_BALANCE`) | Yes | | ||
| | Per address (`TIMER_LIMIT`) | No — the same address still cannot receive again within the timer window | |
e50c877 to
41b7013
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
description
There are wallets that are abusing the usage of the faucet by getting tRBTC every day.
As an example, address 0xC3071E6e19907f7238174BAFac20c5b5e34C81F1
https://explorer.testnet.rootstock.io/address/0xc3071e6e19907f7238174bafac20c5b5e34c81f1?tab=txs
has accumulated more than 5 trbtc.
In order to avoid that level of abuse, we will set up a maximum balance for the receiving address of 0.1 tRBTC.
summary of changes
FILTER_BY_BALANCEandMAX_RECEIVER_BALANCEto control recipient balance checks.