@mintpass/challenge
Version:
MintPass plebbit-js challenge implementation
185 lines (139 loc) • 5.89 kB
Markdown
# MintPass Challenge for Plebbit-js
This directory contains the MintPass challenge implementation for plebbit-js that verifies users own a MintPass NFT.
## Features
- **NFT Ownership Verification**: Checks if users own a MintPass NFT of the required type
- **Transfer Cooldown Protection**: Prevents quick NFT transfers between accounts to bypass verification
- **Chain Flexibility**: Supports different chains where MintPass contracts are deployed
- **ENS Support**: Works with ENS addresses and wallet addresses
- **Type-specific Requirements**: Can require specific token types (SMS=0, Email=1, etc.)
## Installation
For use in plebbit-js projects, clone the mintpass repo alongside your plebbit-js project:
```bash
# Clone mintpass repo
git clone https://github.com/your-username/mintpass.git
# Build the challenge
cd mintpass
yarn install:all
yarn build:challenge
```
## Usage
### Basic Challenge Configuration
```javascript
// Import via file path (not package import)
const challengeSettings = {
path: '../mintpass/challenge/dist/mintpass.js', // Relative path to built challenge
options: {
chainTicker: 'base',
contractAddress: '0x13d41d6B8EA5C86096bb7a94C3557FCF184491b9',
requiredTokenType: '0', // 0 = SMS verification
transferCooldownSeconds: '604800', // 1 week
error: 'You need a MintPass NFT to post. Visit https://mintpass.org/request/{authorAddress}'
}
};
// Set on subplebbit
subplebbit.settings.challenges = [challengeSettings];
```
### Directory Structure
Your project should look like:
```
your-project/
├── plebbit-js/ # Your plebbit-js fork
└── mintpass/ # Cloned mintpass repo
└── challenge/
└── dist/
└── mintpass.js # Built challenge file
```
### Challenge Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `chainTicker` | string | `"base"` | Chain where MintPass contract is deployed |
| `contractAddress` | string | Optional on supported chains | If omitted and `chainTicker` is supported, defaults to the known MintPass deployment for that chain (e.g., Base Sepolia) |
| `requiredTokenType` | string | `"0"` | Required token type (0=SMS, 1=Email, etc.) |
| `transferCooldownSeconds` | string | `"604800"` | Cooldown period after NFT transfer (1 week) |
| `error` | string | Default message | Custom error message for users without NFT |
### Token Types
- **Type 0**: SMS verification
- **Type 1**: Email verification
- **Type 2+**: Future verification methods
### Transfer Cooldown
### Wallet selection and EVM fallback
- When `chainTicker` is `"base"` or `"eth"`, the challenge first looks for `author.wallets[chainTicker]`.
- If that specific wallet is missing, it automatically falls back between `base` and `eth` (e.g., `base → eth` or `eth → base`).
- This makes EVM wallet usage robust when clients store a single EVM wallet entry.
### Default contract addresses
- If `contractAddress` is omitted and `chainTicker` is supported, the challenge uses a known default for that chain (e.g., Base Sepolia reference deployment).
- You can still override `contractAddress` explicitly in settings.
The challenge tracks when NFTs are used by different plebbit accounts and enforces a cooldown period to prevent:
- Quick transfers to bypass bans
- NFT sharing between multiple accounts
- Sybil attacks via NFT circulation
## Development
### Building
```bash
cd challenges
yarn install
yarn build
```
### Testing
The challenge includes comprehensive automated testing that covers both the challenge logic and complete user publishing flow.
#### Quick Start
```bash
cd challenges
yarn test
```
This command automatically:
- Starts a local Hardhat blockchain node
- Deploys the MintPass contract
- Runs the full integration test suite
- Cleans up all processes when complete
#### Manual Testing
For situations where you need to manage the test infrastructure manually:
```bash
# Terminal 1: Start the Hardhat node
cd contracts && npx hardhat node
# Terminal 2: Run tests against the running node
cd challenges && yarn test:manual
```
#### Test Coverage
The automated test suite includes:
- **NFT Ownership Verification**: Tests both success and failure scenarios
- **Complete Publishing Flow**: Simulates real user posting experience
- **Local IPFS Integration**: Tests with isolated local IPFS daemon
- **Challenge/Verification Exchange**: Validates complete challenge workflow
For detailed testing information, see [AUTOMATED_TESTING.md](AUTOMATED_TESTING.md).
### Integration with plebbit-js
The challenge exports a `ChallengeFileFactory` function compatible with plebbit-js:
```javascript
// In your plebbit-js fork
import mintpass from '@mintpass/challenge';
// Register the challenge
Plebbit.challenges.mintpass = mintpass;
// Use in subplebbit settings
const subplebbit = await plebbit.createSubplebbit({
settings: {
challenges: [{
name: 'mintpass',
options: {
contractAddress: '0x...',
requiredTokenType: '0'
}
}]
}
});
```
## Architecture
The challenge follows the plebbit-js challenge pattern:
1. **Wallet Verification**: Validates author's wallet signature
2. **NFT Ownership Check**: Calls `ownsTokenType()` on MintPass contract
3. **Transfer Cooldown**: Tracks NFT usage across plebbit accounts
4. **ENS Support**: Resolves ENS addresses to wallet addresses
## Error Scenarios
| Scenario | Error Message |
|----------|---------------|
| No wallet set | "Author wallet address is not defined" |
| Invalid signature | "The signature of the wallet is invalid" |
| No NFT owned | Custom error with link to verification site |
| NFT in cooldown | "Your MintPass NFT is in cooldown period" |
| Contract call fails | "Failed to check MintPass NFT ownership" |
## License
MIT License - Same as the MintPass project.