A secure, gas-efficient ERC20 token claim contract with signature-based authentication. This contract allows users to claim tokens using cryptographically signed messages from a backend service, ensuring secure and verifiable token distribution.
- Features
- Architecture
- Security Features
- Installation
- Configuration
- Usage
- Testing
- Deployment
- Contract Functions
- Security Considerations
- License
- Contact
- Signature-Based Authentication: Secure token claims using EIP-191 signed messages
- Reentrancy Protection: Built-in protection against reentrancy attacks
- Signature Replay Prevention: One-time use signatures prevent double-spending
- Expiration Support: Time-bound signatures for enhanced security
- Admin Controls: Owner can update token address and backend wallet
- Emergency Withdraw: Owner can withdraw tokens in emergency situations
- Gas Optimized: Efficient contract design for lower transaction costs
- OpenZeppelin Audited: Uses battle-tested OpenZeppelin contracts
The contract implements a signature-based claim system where:
- Backend service generates a signature for eligible users
- Users submit the signature along with claim parameters
- Contract verifies the signature authenticity
- Tokens are transferred to the user if verification passes
The signed message contains:
recipient: Address of the token recipientamount: Amount of tokens to claimnonce: Unique identifier to prevent replay attacksdeadline: Timestamp after which the signature expires
- ReentrancyGuard: Prevents reentrancy attacks
- SafeERC20: Safe token transfers using OpenZeppelin's SafeERC20 library
- Signature Verification: Cryptographic verification of backend signatures
- Ownable: Access control for administrative functions
- Zero Address Checks: Prevents invalid address assignments
- Node.js (v18 or higher)
- npm or yarn
- Hardhat
- Clone the repository:
git clone <repository-url>
cd claim_contract- Install dependencies:
npm install- Create a
.envfile in the root directory:
PRIVATE_KEY=your_private_key_here
INFURA_PROJECT_ID=your_infura_project_id
ETHERSCAN_API_KEY=your_etherscan_api_key
TOKEN_CONTRACT=your_token_contract_address
BACKEND_WALLET=your_backend_wallet_addressPRIVATE_KEY: Private key of the deployer accountINFURA_PROJECT_ID: Infura project ID for RPC accessETHERSCAN_API_KEY: Etherscan API key for contract verificationTOKEN_CONTRACT: Address of the ERC20 token contractBACKEND_WALLET: Address of the wallet that signs claim messages
The project is configured for:
- Sepolia Testnet: For testing deployments
- Ethereum Mainnet: For production deployments
Update hardhat.config.js to add additional networks if needed.
npm run compilenpm testnpm run deploy:sepolianpm run deploy:mainnetnpx hardhat verify --network <network> <contract_address> <token_address> <backend_wallet_address>The test suite includes comprehensive coverage for:
- Contract deployment and initialization
- Token claiming with valid signatures
- Signature replay prevention
- Expiration handling
- Invalid signature rejection
- Admin functions
- Access control
Run tests with:
npm test-
Prepare Environment:
- Ensure
.envfile is configured - Fund deployer account with ETH for gas
- Ensure
-
Deploy Contract:
npm run deploy:sepolia # For testnet # or npm run deploy:mainnet # For mainnet
-
Verify Contract:
npx hardhat verify --network sepolia <contract_address> <token_address> <backend_wallet>
-
Fund Contract: Transfer ERC20 tokens to the deployed contract address for users to claim.
Claims tokens using a backend-signed message.
Parameters:
amount: Amount of tokens to claimnonce: Unique nonce for this claimdeadline: Signature expiration timestampsignature: Backend signature
Requirements:
- Signature must not be expired
- Signature must not have been used before
- Contract must have sufficient balance
- Signature must be valid
Checks if a signature has already been used.
verifySignature(address recipient, uint256 amount, uint256 nonce, uint256 deadline, bytes memory signature)
Verifies a signature without executing the claim.
Returns the current token balance of the contract.
Updates the token contract address.
Updates the backend wallet address that signs messages.
Withdraws tokens from the contract (owner only).
-
Backend Wallet Security: The backend wallet private key must be kept secure. Compromise of this key allows unauthorized token claims.
-
Nonce Management: Ensure nonces are unique and properly tracked on the backend to prevent signature reuse.
-
Deadline Management: Set appropriate deadlines for signatures to balance security and user experience.
-
Token Funding: Only fund the contract with tokens that users are eligible to claim.
-
Access Control: The owner address should be a multisig wallet for production deployments.
-
Signature Format: Backend must use the exact same message format as the contract:
keccak256(abi.encodePacked(recipient, amount, nonce, deadline))
This project is licensed under the MIT License.
Telegram: @moooncity
For questions, support, or collaboration opportunities, feel free to reach out via Telegram.
Built with β€οΈ using Solidity, Hardhat, and OpenZeppelin