算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
jb-simplify【设计与创意】Checklist to simplify Juicebox project designs. Reduce custom contracts by leveraging native protocol mechanics.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Before writing custom contracts, run through this checklist to find simpler solutions.
Native mechanics > Off-the-shelf hooks > Custom hooks > Custom contracts
Every level of abstraction you can avoid:
| What You Want | Simpler Solution |
|---|---|
| Mint NFTs on payment | Use nana-721-hook-v5 directly |
| Buy tokens from DEX if cheaper | Use nana-buyback-hook-v5 directly |
| Restrict who can pay | Use off-chain allowlists or payment metadata |
| Different tokens per tier | Use 721 hook tiers with different prices |
| Cap individual payments | Consider if this is actually needed |
Only write a custom pay hook if: You need logic that modifies payment recording that no existing hook provides.
| What You Want | Simpler Solution |
|---|---|
| Burn NFT to redeem | Use nana-721-hook-v5 - it already does this |
| Pro-rata redemption against surplus | Set cashOutTaxRate: 0 - native behavior |
| Partial redemption (bonding curve) | Set cashOutTaxRate to desired value |
| Time-locked redemptions | Use ruleset with pauseCashOut: true, queue future ruleset |
| Redemption against external pool | This might actually need a custom hook |
Only write a custom cash out hook if: Redemption value must come from somewhere other than project surplus.
| What You Want | Simpler Solution |
|---|---|
| Send to multiple addresses | Use multiple splits with direct beneficiaries |
| Send to another JB project | Set projectId in the split |
| Add to project balance instead of paying | Set preferAddToBalance: true |
| Restrict who can claim | Set beneficiary to a multisig/contract |
| Swap tokens before forwarding | Yes, need split hook |
| Add to LP position | Yes, need split hook |
Only write a custom split hook if: You need to transform tokens or interact with external protocols.
| What You Want | Simpler Solution |
|---|---|
| Monthly distributions | One ruleset with duration: 30 days |
| Increasing/decreasing token issuance | Use weightCutPercent for automatic issuance cut |
| Different phases over time | Queue rulesets only for actual changes |
| Vesting over 12 months | One cycling ruleset, NOT 12 queued rulesets |
Only queue multiple rulesets if: Configuration actually changes between periods.
| What You Want | Simpler Solution |
|---|---|
| NFT minting on payment | Use nana-721-hook-v5 directly |
| Different prices per tier | Configure tiers in 721 hook |
| Static artwork per tier | Use encodedIPFSUri in tier config |
| Dynamic/generative art | Implement IJB721TokenUriResolver only |
| Composable/layered NFTs | Implement IJB721TokenUriResolver only |
| On-chain SVG | Implement IJB721TokenUriResolver only |
| Custom minting logic | This might need a custom hook |
Only write a custom pay/data hook if: You need to change how the 721 hook processes payments. For custom content, use the resolver interface.
Reference: banny-retail-v5 shows composable NFTs using only a custom resolver.
Extending the 721-hook (not just resolver) is necessary when you need to change treasury mechanics, not just content:
| What You Want | Why You Need Custom Delegate |
|---|---|
| Dynamic cash out weights | Redemption value changes based on outcomes |
| First-owner tracking | Rewards go to original minter, not current holder |
| Phase-based restrictions | Different rules during different game phases |
| On-chain governance for outcomes | Scorecard voting determines payouts |
Reference: defifa-collection-deployer-v5 shows prediction games with dynamic weights.
| What You Want | Simpler Solution |
|---|---|
| Vesting | Payout limits + cycling rulesets |
| Treasury reserve | Surplus allowance |
| NFT-gated treasury | 721 hook + native cash outs |
| Immutable configuration | Transfer ownership to burn address |
| Multi-sig control | Set owner to Safe/multisig |
| Governance | Use existing governance frameworks |
Ask these questions in order. Stop at the first "yes":
❌ WRONG: Create DataHookWrapper that delegates to 721 hook
✅ RIGHT: Use 721 hook directly, achieve goals via ruleset config
❌ WRONG: VestingSplitHook that holds funds and releases over time
✅ RIGHT: Payout limits reset each cycle, achieving the same result
❌ WRONG: Queue 12 identical rulesets with different start times
✅ RIGHT: One ruleset with duration: 30 days that cycles automatically
❌ WRONG: Split hook that just forwards ETH to an address
✅ RIGHT: Set the address as the split beneficiary directly
❌ WRONG: Custom hook calculating pro-rata share of surplus
✅ RIGHT: cashOutTaxRate: 0 gives linear redemption natively
❌ WRONG: Write custom pay hook to generate dynamic NFT metadata
✅ RIGHT: Use 721 hook + custom IJB721TokenUriResolver for content only
| Solution | Gas Cost | Audit Risk | UI Support |
|---|---|---|---|
| Native config only | Lowest | Lowest | Full |
| Off-the-shelf hooks | Low | Low | Full |
| Custom token URI resolver | Low | Low | Full |
| Custom split hook | Medium | Medium | Partial |
| Custom pay hook | Medium | Medium | Partial |
| Extended 721-hook delegate | Medium-High | Medium-High | Custom UI needed |
| Custom cash out hook | High | High | Limited |
| Full custom system | Highest | Highest | None |
Not all complexity is bad. These patterns justify extending hooks:
| Pattern | Justification |
|---|---|
| Prediction games (Defifa) | Dynamic weights can't be done any other way |
| Composable NFTs (Banny) | Resolver-only keeps treasury mechanics standard |
| Phase-based games | Rulesets + custom delegate is cleaner than alternatives |
Key insight: Extend hooks for treasury mechanics, use resolvers for content only.
Before finalizing your design, verify:
If all boxes are checked and you still need custom code, proceed with confidence that it's actually necessary.
/jb-patterns - Common design patterns with examples/jb-project - Project deployment/jb-pay-hook - When you DO need a custom pay hook/jb-cash-out-hook - When you DO need a custom cash out hook/jb-split-hook - When you DO need a custom split hook