This PR implements standardized SafeERC20 usage for non-compliant tokens across the Credence Contracts codebase, addressing potential silent failures when interacting with tokens that don't follow standard ERC20 return value patterns.
- Issue: #131 - Standardize SafeERC20 usage for non-compliant tokens
- Goal: Replace direct ERC20 calls with SafeERC20 wrappers and ensure consistent error handling
- Comprehensive safe token operations with standardized error handling
- Input validation for amounts and addresses
- Support for non-compliant tokens that don't return boolean values
- Consistent panic messages for better debugging
// Safe transfer operations
safe_transfer(e, recipient, amount)
safe_transfer_from(e, owner, amount)
safe_require_allowance(e, owner, amount)
// Safe approval operations
safe_approve(e, spender, amount)
safe_increase_allowance(e, spender, added_value)
force_approve(e, spender, amount)- ✅
token_integration.rs- Uses safe wrapper functions - ✅
lib.rs- Updatedincrease_bond()function - ✅
verifier.rs- Safe staking operations - ✅
claims.rs- Safe claim processing
- Edge case testing for all safe token functions
- Non-compliant token handling validation
- Error message consistency verification
- Integration tests with existing modules
- Mock token implementation for edge cases
- ✅ Valid parameter handling
- ✅ Invalid amount validation
- ✅ Zero amount early returns
- ✅ Missing token configuration
- ✅ Insufficient allowance scenarios
- ✅ Address validation
- ✅ Overflow protection
- ✅ Error message consistency
// Direct token operations with inconsistent error handling
let token_client = TokenClient::new(&e, &token_addr);
token_client.transfer_from(&contract_address, &caller, &contract_address, &amount);// Safe token operations with consistent validation and error handling
safe_token::safe_transfer_from(&e, &caller, amount);- Consistent Error Messages: All token operations use standardized error messages
- Input Validation: Automatic validation of amounts and addresses
- Non-Compliant Token Support: Handles tokens that don't return boolean values
- Overflow Protection: Built-in overflow checks for all arithmetic operations
- Zero Address Protection: Validates token addresses to prevent zero address transfers
- Allowance Safety: Proper allowance checking before transfer_from operations
All token movement paths have been migrated:
- ✅ Bond creation (
create_bond,top_up,increase_bond) - ✅ Bond withdrawals (
withdraw_bond,withdraw_early) - ✅ Verifier staking (
register_with_stake,withdraw_stake) - ✅ Claims processing (
process_claims) - ✅ Fee transfers (via token_integration)
- ✅ Penalty transfers (via token_integration)
- ✅ All existing APIs preserved
- ✅ No breaking changes to public interfaces
- ✅ Enhanced error messages for better debugging
- ✅ Same functionality with improved safety
- Minimal overhead from additional validation (few extra checks)
- Same gas costs for successful operations
- Better error handling reduces failed transaction costs
- Consistent behavior across all token operations
contracts/credence_bond/src/safe_token.rs- Safe token operations modulecontracts/credence_bond/src/safe_token_tests.rs- Comprehensive test suiteSAFE_ERC20_MIGRATION_SUMMARY.md- Detailed migration documentation
contracts/credence_bond/src/token_integration.rs- Uses safe operationscontracts/credence_bond/src/lib.rs- Migrated direct token callscontracts/credence_bond/src/verifier.rs- Uses safe token operationscontracts/credence_bond/src/claims.rs- Uses safe token operations
# Run safe token tests
cargo test safe_token
# Run all credence bond tests
cargo test -p credence_bond- Deploy to testnet
- Test with various token types (compliant and non-compliant)
- Verify error handling for## Objective Reject empty vectors with a typed error rather than downstream panics.
Closes #757
What does an attacker get if this check is missing? If the empty vector check is missing, an attacker could:
- Submit empty batches to
create_batch_bondsor similar batch functions. This avoids loop-based panics and effectively wastes node computation/storage resources (gas) and pollutes the event stream with emptybatch_bonds_createdevents without providing economic value. - In administrative functions like
set_accepted_tokens, passing an empty vector unintentionally clears all accepted tokens without error, which causes unexpected and difficult-to-debug "Unauthorized Token" failures downstream for all users trying to create bonds. - In functions processing items without pre-validation, empty vectors could cause "index out of bounds" or
.unwrap()panics.
By checking .is_empty() centrally via require_non_empty_vec(v) and returning ContractError::EmptyBatch, we surface a strongly-typed error that off-chain indexers and user interfaces can handle safely without hitting generic Soroban 500 or HostError downstream.
The added check (v.is_empty()) is an O(1) operation inside the Soroban WASM runtime, consisting of a single length comparison. The cost impact on the hot path (like create_batch_bonds) is negligible and entirely offset by preventing execution of an empty loop and emitting an empty batch event.
2. Run integration tests with various token types
3. Monitor for issues with non-compliant tokens
4. Validate error handling in production scenarios
- Security audit of safe token implementation
- Final testing on testnet
- Gradual rollout with monitoring
- Emergency rollback plan if needed
- API Documentation: Updated with new safety features
- Migration Guide:
SAFE_ERC20_MIGRATION_SUMMARY.md - Test Documentation: Comprehensive test suite documentation
- Fixes: #131 - Standardize SafeERC20 usage for non-compliant tokens
- Related: Token safety improvements across the ecosystem
- Prevents silent failures with non-compliant tokens
- Consistent error handling improves debugging
- Input validation prevents common vulnerabilities
- No breaking changes to existing APIs
- Backward compatible implementation
- Enhanced error messages only
- Few extra validation checks
- No impact on successful operations
- Better error handling reduces costs
This PR represents a significant security improvement for token operations while maintaining full backward compatibility.