npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bbuilders/djeon402-contracts

v2.0.2

Published

DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support

Downloads

53

Readme

@bbuilders/djeon402-contracts

DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token SDK with x402 protocol support

Build your own x402-compatible payment token in minutes by importing DONGJEON402.sol

License: MIT Solidity


📖 Table of Contents


🎯 What is DONGJEON402?

DONGJEON402 (also known as DJEON402) is a production-ready smart contract SDK for building gasless payment tokens that support the x402 protocol (HTTP 402 Payment Required).

Why DONGJEON402?

  • Zero Gas Fees: Users can transfer tokens without holding native ETH
  • Enterprise Ready: Role-based access control, compliance features, upgradeable
  • Developer Friendly: Simple inheritance pattern, extensive examples
  • Battle Tested: Based on OpenZeppelin contracts with additional security layers

x402 Protocol Support

The x402 protocol enables HTTP 402 Payment Required responses to trigger on-chain payments using EIP-3009 (TransferWithAuthorization), allowing gasless, off-chain authorized transfers.


✨ Features

Core Token Features

  • ERC-20 - Standard token interface
  • ERC-2612 Permit - Gasless approvals via signatures
  • EIP-3009 - TransferWithAuthorization for x402 compatibility
  • 18 Decimals - Standard ERC-20 decimal precision

Enterprise Features

  • Role-Based Access Control (RBAC) - 6 roles: Admin, Minter, Burner, Pauser, Blacklister, KYC Manager
  • Blacklist - Compliance and regulatory requirements
  • Pausable - Emergency stop mechanism
  • KYC Registry - Optional 5-tier KYC level system with configurable daily limits
  • UUPS Upgradeable - Safely upgrade contract logic
  • Diamond-Ready Storage - Isolated storage slots for future EIP-2535 migration

🚀 Installation

Using npm (Recommended)

npm install @bbuilders/djeon402-contracts

Using Foundry

Note: Private repo인 경우 GitHub 인증(PAT 토큰)이 필요합니다.

forge install b-builders/dongjeon402-contract-sdk

Add to your remappings.txt:

@bbuilders/djeon402-contracts/=lib/dongjeon402-contract-sdk/

🎯 Quick Start

1. Simplest Token (Just Inherit)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@bbuilders/djeon402-contracts/src/DONGJEON402.sol";

contract MyToken is DONGJEON402 {
    // That's it! All features inherited:
    // - ERC-20 with 18 decimals
    // - Gasless transfers (EIP-3009)
    // - Permit (ERC-2612)
    // - RBAC, Blacklist, Pausable
    // - UUPS upgradeable
}

2. Deploy with Proxy

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@bbuilders/djeon402-contracts/src/DONGJEON402.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployMyToken {
    function deploy() external returns (address) {
        // Step 1: Deploy implementation
        DONGJEON402 implementation = new DONGJEON402();

        // Step 2: Encode initialization data
        bytes memory initData = abi.encodeWithSelector(
            DONGJEON402.initialize.selector,
            msg.sender,        // admin address
            "My Token",        // token name
            "MTK"              // token symbol
        );

        // Step 3: Deploy proxy
        ERC1967Proxy proxy = new ERC1967Proxy(
            address(implementation),
            initData
        );

        // Step 4: Return proxy address (this is your token address)
        return address(proxy);
    }
}

3. Use the Token

// Wrap proxy as DONGJEON402 interface
DONGJEON402 token = DONGJEON402(proxyAddress);

// Mint tokens (requires MINTER_ROLE)
token.mint(user, 1000 * 10**18); // 1000 tokens (18 decimals)

// Standard ERC-20 transfers
token.transfer(recipient, 100 * 10**18);

// Gasless transfer with signature (x402 compatible)
token.transferWithAuthorization(
    from,
    to,
    amount,
    validAfter,
    validBefore,
    nonce,
    v, r, s
);

// Pause in emergency (requires PAUSER_ROLE)
token.pause();

📚 Examples

See the examples/ directory for complete working examples:

1. BasicToken.sol

The simplest possible implementation - just inherit DONGJEON402.

import "@bbuilders/djeon402-contracts/src/DONGJEON402.sol";

contract BasicToken is DONGJEON402 {
    // Ready to use!
}

2. CustomToken.sol ⭐ Recommended for Custom Tokens

Deploy custom tokens with configurable name, symbol, and initial supply.

CustomTokenDeployer deployer = new CustomTokenDeployer();

// Deploy fully custom token
address token = deployer.deployCustomToken(
    admin,
    "My Token",    // custom name
    "MTK",         // custom symbol
    1000000        // 1M tokens initial supply
);

// Or use pre-configured examples
address usds = deployer.deployUSDStablecoin(admin);      // USD Stablecoin
address krws = deployer.deployKRWStablecoin(admin);      // Korean Won
address eurs = deployer.deployEuroStablecoin(admin);     // Euro

3. StablecoinWithInitialSupply.sol

Mint initial supply during deployment.

contract MyStablecoin is DONGJEON402 {
    function initializeWithSupply(
        address admin,
        string memory name,
        string memory symbol,
        uint256 initialSupply
    ) public initializer {
        initialize(admin, name, symbol);
        _mint(admin, initialSupply);
    }
}

4. RewardToken.sol

Automatically give 1% rewards on every transfer.

contract RewardToken is DONGJEON402 {
    uint256 public rewardRate = 100; // 1%

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._afterTokenTransfer(from, to, amount);

        if (from != address(0) && to != address(0)) {
            uint256 reward = (amount * rewardRate) / 10000;
            if (reward > 0) _mint(to, reward);
        }
    }
}

5. DeployExample.sol

Complete deployment example with UUPS proxy pattern.

See examples/ directory for all examples and examples/README.md for detailed usage instructions.


📖 API Reference

Core Functions

initialize(address admin, string name, string symbol)

Initialize the contract (called once during deployment via proxy).

function initialize(
    address admin,
    string memory name,
    string memory symbol
) external initializer

Standard ERC-20

function name() external view returns (string)
function symbol() external view returns (string)
function decimals() external view returns (uint8)  // Returns 18
function totalSupply() external view returns (uint256)
function balanceOf(address account) external view returns (uint256)
function transfer(address to, uint256 amount) external returns (bool)
function approve(address spender, uint256 amount) external returns (bool)
function transferFrom(address from, address to, uint256 amount) external returns (bool)
function allowance(address owner, address spender) external view returns (uint256)

ERC-2612 Permit (Gasless Approvals)

function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external

EIP-3009 (x402 Protocol)

// Anyone can execute (relayer pays gas)
function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external

// Only the receiver (to == msg.sender) can execute
function receiveWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external

// Cancel an unused authorization (marks nonce as used)
function cancelAuthorization(
    address authorizer,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external

// Check if a nonce has been used
function authorizationState(
    address authorizer,
    bytes32 nonce
) external view returns (bool)

Admin Functions

Minting & Burning

function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE)
function burn(uint256 amount) external onlyRole(BURNER_ROLE)

Pause/Unpause

function pause() external onlyRole(PAUSER_ROLE)
function unpause() external onlyRole(PAUSER_ROLE)
function paused() external view returns (bool)

Blacklist

function blacklist(address account) external onlyRole(BLACKLISTER_ROLE)
function unBlacklist(address account) external onlyRole(BLACKLISTER_ROLE)
function isBlacklisted(address account) external view returns (bool)

Role Management

bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant BLACKLISTER_ROLE = keccak256("BLACKLISTER_ROLE");
bytes32 public constant KYC_MANAGER_ROLE = keccak256("KYC_MANAGER_ROLE");

function hasRole(bytes32 role, address account) external view returns (bool)
function grantRole(bytes32 role, address account) external onlyRole(DEFAULT_ADMIN_ROLE)
function revokeRole(bytes32 role, address account) external onlyRole(DEFAULT_ADMIN_ROLE)
function renounceRole(bytes32 role, address account) external

KYC Registry

KYC Levels:

| Level | Name | Default Daily Limit | |-------|-------|-------------------| | 0 | None | $0 (no access) | | 1 | Tier1 | $1,000 | | 2 | Tier2 | $10,000 | | 3 | Tier3 | $1,000,000 | | 4 | Tier4 | Unlimited |

Daily limits are configurable by admin via setLevelLimit(). Defaults are set on deployment.

// KYC Management (admin only)
function verifyKYC(address user, KYCLevel level, uint256 expiryDate, string kycHash) external onlyKYCAdmin
function updateKYC(address user, KYCLevel level, uint256 expiryDate) external onlyKYCAdmin
function revokeKYC(address user) external onlyKYCAdmin

// Level Limit Configuration (admin only)
function setLevelLimit(KYCLevel level, uint256 newLimit) external onlyKYCAdmin
function setDailyLimit(address user, uint256 newLimit) external onlyKYCAdmin

// View Functions
function getLevelLimit(KYCLevel level) external view returns (uint256)
function getKYCData(address user) external view returns (KYCLevel, uint256, string, bool, uint256, uint256)
function getKYCLevel(address user) external view returns (KYCLevel)
function isKYCValid(address user) external view returns (bool)
function getRemainingDailyLimit(address user) external view returns (uint256)
function checkDailyLimit(address user, uint256 amount) external returns (bool)

Upgradeability (UUPS)

function upgradeToAndCall(address newImplementation, bytes data) external onlyRole(DEFAULT_ADMIN_ROLE)
function proxiableUUID() external view returns (bytes32)

🏗️ Architecture

Storage Layout (Diamond-Ready)

DONGJEON402 uses isolated storage slots to enable future migration to EIP-2535 (Diamond Standard):

src/
├── DONGJEON402.sol              # Main contract
├── storage/
│   ├── TokenStorage.sol         # balances, allowances, supply
│   ├── PermitStorage.sol        # nonces, DOMAIN_SEPARATOR
│   ├── AuthorizationStorage.sol # authorization states
│   ├── AccessStorage.sol        # roles
│   ├── BlacklistStorage.sol     # blacklisted addresses
│   ├── PausableStorage.sol      # paused state
│   └── KYCStorage.sol           # KYC levels
└── interfaces/
    └── IERC3009.sol             # EIP-3009 interface

Each storage contract defines its own namespace to prevent collisions:

library TokenStorage {
    bytes32 constant STORAGE_SLOT = keccak256("dongjeon402.storage.token");

    struct Layout {
        mapping(address => uint256) balances;
        mapping(address => mapping(address => uint256)) allowances;
        uint256 totalSupply;
        string name;
        string symbol;
    }
}

Proxy Pattern (UUPS)

User → ERC1967Proxy → DONGJEON402 Implementation
                       ↓
                   Storage (in Proxy)
  • All state is stored in the proxy contract
  • Implementation contract contains logic only
  • Upgrades change the implementation address in the proxy
  • User always interacts with the same proxy address

🔒 Security

Audits

  • Based on OpenZeppelin Contracts (industry standard)
  • Custom storage patterns reviewed for upgrade safety
  • UUPS upgrade pattern prevents unauthorized upgrades

Best Practices

  1. Always deploy via proxy - Direct deployment of DONGJEON402 should only be used as implementation
  2. Secure admin keys - Admin role can upgrade contract, mint, pause
  3. Test upgrades - Use forge test to verify upgrade compatibility
  4. Monitor events - All critical actions emit events
  5. Use multi-sig - Consider using Gnosis Safe for admin role

Known Limitations

  • 18 decimals (standard ERC-20, set during initialization)
  • UUPS upgrades require admin role
  • Blacklisted addresses cannot transfer or receive

🛠️ Development

Build

forge build

Test

forge test

Deploy

Refer to the examples/DeployExample.sol for deployment patterns, or create your own deployment script:

# Create your deployment script
forge script script/YourDeploy.s.sol --rpc-url <RPC_URL> --broadcast

📦 Package Contents

dongjeon402-contract-sdk/
├── src/
│   ├── DONGJEON402.sol           # Main contract
│   ├── KYCRegistry.sol           # Optional KYC registry
│   ├── interfaces/               # Contract interfaces
│   │   └── IERC3009.sol
│   └── storage/                  # Diamond-ready storage (7 files)
├── examples/                     # 5 usage examples
│   ├── BasicToken.sol
│   ├── CustomToken.sol           # ⭐ NEW - Custom tokens
│   ├── StablecoinWithInitialSupply.sol
│   ├── RewardToken.sol
│   └── DeployExample.sol
├── lib/                          # Foundry dependencies
├── foundry.toml                  # Foundry config
├── remappings.txt                # Import remappings
└── package.json                  # npm config

🤝 Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Ensure forge test passes
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details.


🔗 Links

  • GitHub: (Update with your repository URL)
  • Examples: ./examples/
  • NPM: @bbuilders/djeon402-contracts (when published)

Note: Update URLs in package.json before publishing


📦 Related Packages


💬 Support

  • Issues: Create issues in your repository
  • Documentation: See examples/README.md for usage guides

Built with ❤️ for the x402 protocol ecosystem