{"_id":"@bbuilders/djeon402-contracts","_rev":"5-0d8f143317decf51fa26af00c4e725d4","name":"@bbuilders/djeon402-contracts","dist-tags":{"latest":"3.1.0"},"versions":{"2.0.0":{"name":"@bbuilders/djeon402-contracts","version":"2.0.0","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"author":{"name":"DJEON402 Team","email":"dev@djeon402.com"},"license":"MIT","_id":"@bbuilders/djeon402-contracts@2.0.0","maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"homepage":"https://github.com/djeon402/contracts#readme","bugs":{"url":"https://github.com/djeon402/contracts/issues"},"dist":{"shasum":"95e93a120d75e56e2f1f118c0fecf1c6151c01e6","tarball":"https://registry.npmjs.org/@bbuilders/djeon402-contracts/-/djeon402-contracts-2.0.0.tgz","fileCount":2580,"integrity":"sha512-FGJBQ18hKrB+hNNkc0Y6WLUDycKoWWqV/Q61E3F8+d/CdcZ5G+cCMUTu8OWteL5zD4umKzmCZwQWMcmxwyvOVg==","signatures":[{"sig":"MEYCIQC9TwOMn776KZ6iFm14ok3lY1RdwidUjuqALJRFpAePkgIhALOp/o6GzM+KgKfCxiUCLaGUPjnHbhldREkUmUEd5hQQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37461999},"scripts":{"fmt":"forge fmt","lint":"solhint 'src/**/*.sol'","test":"forge test","build":"forge build","clean":"forge clean","prepare":"bun run setup:submodules && simple-git-hooks","lint:fix":"solhint 'src/**/*.sol' --fix","fmt:check":"forge fmt --check","postinstall":"bun run setup:submodules","setup:submodules":"git submodule update --init --recursive || echo 'Submodules not available, using npm dependencies'"},"_npmUser":{"name":"b-builders","email":"dev@bbuilders.xyz"},"repository":{"url":"git+https://github.com/djeon402/contracts.git","type":"git"},"_npmVersion":"11.3.0","description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","directories":{},"lint-staged":{"src/**/*.sol":["forge fmt","solhint"]},"_nodeVersion":"24.2.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"solhint":"^6.0.3","lint-staged":"^16.2.7","simple-git-hooks":"^2.13.1"},"simple-git-hooks":{"pre-commit":"bunx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/djeon402-contracts_2.0.0_1775536828538_0.8875955052683082","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@bbuilders/djeon402-contracts","version":"2.0.1","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"author":{"name":"bbuilders","email":"dev@bbuilders.xyz"},"license":"MIT","_id":"@bbuilders/djeon402-contracts@2.0.1","maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"dist":{"shasum":"692ce320501e8a0c54e460f0f69db4bba224ddd1","tarball":"https://registry.npmjs.org/@bbuilders/djeon402-contracts/-/djeon402-contracts-2.0.1.tgz","fileCount":2580,"integrity":"sha512-XnlsGlz1VKLwsa4ktTBK0CT/5OM7eu07kLdWdJeJT6wCBxUtb8zhu3wtvfnix12Asfs0QPBJ5E1Qr9dIKGOrVQ==","signatures":[{"sig":"MEUCIQDXMzOEZXf0omki2BsDnQxJOIP959HU8u/d/xikdqa61QIgEcVisHSVnR+DJ8uSai221mm4S3vQaTXaFHnm1G5qLVA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37461713},"scripts":{"fmt":"forge fmt","lint":"solhint 'src/**/*.sol'","test":"forge test","build":"forge build","clean":"forge clean","prepare":"bun run setup:submodules && simple-git-hooks","lint:fix":"solhint 'src/**/*.sol' --fix","fmt:check":"forge fmt --check","postinstall":"bun run setup:submodules","setup:submodules":"git submodule update --init --recursive || echo 'Submodules not available, using npm dependencies'"},"_npmUser":{"name":"b-builders","email":"dev@bbuilders.xyz"},"_npmVersion":"11.3.0","description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","directories":{},"lint-staged":{"src/**/*.sol":["forge fmt","solhint"]},"_nodeVersion":"24.2.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"solhint":"^6.0.3","lint-staged":"^16.2.7","simple-git-hooks":"^2.13.1"},"simple-git-hooks":{"pre-commit":"bunx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/djeon402-contracts_2.0.1_1775541485325_0.8490748978031979","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@bbuilders/djeon402-contracts","version":"2.0.2","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"author":{"name":"bbuilders","email":"dev@bbuilders.xyz"},"license":"MIT","_id":"@bbuilders/djeon402-contracts@2.0.2","maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"dist":{"shasum":"562177dfd9e99358694f9813525ceeb63b208fbf","tarball":"https://registry.npmjs.org/@bbuilders/djeon402-contracts/-/djeon402-contracts-2.0.2.tgz","fileCount":2580,"integrity":"sha512-d0+7CaNDORO4xarbQwJuAr25EnRrHWJID+ablcwdMG8VnEEzSxDIvjpIu3nBBNMCLkqELawmPsedFGOOKXxmxw==","signatures":[{"sig":"MEUCIQD6vCPtttNDNwm3/67Ps+tvxyUlOfqC3HUwB6iMGpdNmwIgcjZ40fRGC2y3Q7EWdSq24+uUs1bABOPs24HElxkzJe0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37464911},"scripts":{"fmt":"forge fmt","lint":"solhint 'src/**/*.sol'","test":"forge test","build":"forge build","clean":"forge clean","prepare":"bun run setup:submodules && simple-git-hooks","lint:fix":"solhint 'src/**/*.sol' --fix","fmt:check":"forge fmt --check","postinstall":"bun run setup:submodules","setup:submodules":"git submodule update --init --recursive || echo 'Submodules not available, using npm dependencies'"},"_npmUser":{"name":"b-builders","email":"dev@bbuilders.xyz"},"_npmVersion":"11.3.0","description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","directories":{},"lint-staged":{"src/**/*.sol":["forge fmt","solhint"]},"_nodeVersion":"24.2.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"solhint":"^6.0.3","lint-staged":"^16.2.7","simple-git-hooks":"^2.13.1"},"simple-git-hooks":{"pre-commit":"bunx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/djeon402-contracts_2.0.2_1775561524031_0.09828386574722492","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@bbuilders/djeon402-contracts","version":"3.0.0","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"author":{"name":"bbuilders","email":"dev@bbuilders.xyz"},"license":"MIT","_id":"@bbuilders/djeon402-contracts@3.0.0","maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"dist":{"shasum":"aa1a3e3200e4cdd2af25d8797e8653187a234eaf","tarball":"https://registry.npmjs.org/@bbuilders/djeon402-contracts/-/djeon402-contracts-3.0.0.tgz","fileCount":2583,"integrity":"sha512-+53PthTKn/NCNa8iEZEWL+XkHeVSnTyQAZALY4OdPzvJ+LqQ5K2/z+iHVWrJK6S79ZMveDjmssY84HB4IWaC7g==","signatures":[{"sig":"MEQCIEUbaXmz7FPik7vhEoLI45+cZT0qwQmjhUWWkBuZ0Xb6AiBd6iq/Fabf3LQuB8iaJlDGzPUqgYSQzxgkf7lFAHK1Ug==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37491558},"scripts":{"fmt":"forge fmt","lint":"solhint 'src/**/*.sol'","test":"forge test","build":"forge build","clean":"forge clean","prepare":"bun run setup:submodules && simple-git-hooks","lint:fix":"solhint 'src/**/*.sol' --fix","fmt:check":"forge fmt --check","postinstall":"bun run setup:submodules","setup:submodules":"git submodule update --init --recursive || echo 'Submodules not available, using npm dependencies'"},"_npmUser":{"name":"b-builders","email":"dev@bbuilders.xyz"},"_npmVersion":"11.3.0","description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","directories":{},"lint-staged":{"src/**/*.sol":["forge fmt","solhint"]},"_nodeVersion":"24.2.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"solhint":"^6.0.3","lint-staged":"^16.2.7","simple-git-hooks":"^2.13.1"},"simple-git-hooks":{"pre-commit":"bunx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/djeon402-contracts_3.0.0_1784531227629_0.41239885840163515","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@bbuilders/djeon402-contracts","version":"3.1.0","description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"license":"MIT","author":{"name":"bbuilders","email":"dev@bbuilders.xyz"},"scripts":{"prepare":"bun run setup:submodules && simple-git-hooks","postinstall":"bun run setup:submodules","setup:submodules":"git submodule update --init --recursive || echo 'Submodules not available, using npm dependencies'","build":"forge build","test":"forge test","clean":"forge clean","fmt":"forge fmt","fmt:check":"forge fmt --check","lint":"solhint 'src/**/*.sol'","lint:fix":"solhint 'src/**/*.sol' --fix"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"lint-staged":"^16.2.7","simple-git-hooks":"^2.13.1","solhint":"^6.0.3"},"simple-git-hooks":{"pre-commit":"bunx lint-staged"},"lint-staged":{"src/**/*.sol":["forge fmt","solhint"]},"_id":"@bbuilders/djeon402-contracts@3.1.0","_nodeVersion":"24.2.0","_npmVersion":"11.3.0","dist":{"integrity":"sha512-s2dyYuRNjqGe6C/rl52PPF2nsCgy3tpi7b7RsK3uHlTZNVvFLtx5bkyvlLI9n5xmzb+/vrqxnyIapw17ioai+Q==","shasum":"1c928b57de7c8e1450617d7e8311bbc7e05f47ea","tarball":"https://registry.npmjs.org/@bbuilders/djeon402-contracts/-/djeon402-contracts-3.1.0.tgz","fileCount":2589,"unpackedSize":37511040,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDba+NSIlGBgHdx76t/Z/FVLoQBEFJMS1A2wTMelJDxiAiAUXzjiPj/wOCwT0koQ9dbZ+Oosu1nQUskK5oxUKyFdzQ=="}]},"_npmUser":{"name":"b-builders","email":"dev@bbuilders.xyz"},"directories":{},"maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/djeon402-contracts_3.1.0_1784988118153_0.4938087931515265"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-07T04:40:28.451Z","modified":"2026-07-25T14:01:58.686Z","2.0.0":"2026-04-07T04:40:29.196Z","2.0.1":"2026-04-07T05:58:06.013Z","2.0.2":"2026-04-07T11:32:04.823Z","3.0.0":"2026-07-20T07:07:07.988Z","3.1.0":"2026-07-25T14:01:58.525Z"},"author":{"name":"bbuilders","email":"dev@bbuilders.xyz"},"license":"MIT","keywords":["ethereum","solidity","smart-contracts","eip-3009","x402","gasless","payment","erc20","erc2612","kyc","upgradeable","uups","diamond"],"description":"DONGJEON402 (DJEON402) - Enterprise-grade gasless payment token contracts with EIP-3009 (x402) support","maintainers":[{"name":"b-builders","email":"dev@bbuilders.xyz"}],"readme":"# @bbuilders/djeon402-contracts\n\n## What's New in 3.0\n\n**Breaking changes:**\n\n- **Token decimals changed to 6** (USDC/x402 convention) — matches the `10**6` limit encoding used by ComplianceRegistry/KYCRegistry\n- `KYCRegistry.checkDailyLimit` is now restricted to the KYC admin or approved providers (it mutates `dailySpent`; unrestricted access allowed third parties to inflate a user's daily spend)\n- Removed unused `RegistryNotSet` error declaration\n\n> **DONGJEON402 (DJEON402)** - Enterprise-grade gasless payment token SDK with x402 protocol support\n\nBuild your own x402-compatible payment token in minutes by importing DONGJEON402.sol\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Solidity](https://img.shields.io/badge/Solidity-^0.8.20-blue.svg)](https://soliditylang.org/)\n\n---\n\n## 📖 Table of Contents\n\n- [What is DONGJEON402?](#what-is-dongjeon402)\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Examples](#examples)\n- [API Reference](#api-reference)\n- [Architecture](#architecture)\n- [Security](#security)\n- [License](#license)\n\n---\n\n## 🎯 What is DONGJEON402?\n\n**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).\n\n### Why DONGJEON402?\n\n- **Zero Gas Fees**: Users can transfer tokens without holding native ETH\n- **Enterprise Ready**: Role-based access control, compliance features, upgradeable\n- **Developer Friendly**: Simple inheritance pattern, extensive examples\n- **Battle Tested**: Based on OpenZeppelin contracts with additional security layers\n\n### x402 Protocol Support\n\nThe x402 protocol enables HTTP 402 Payment Required responses to trigger on-chain payments using **EIP-3009 (TransferWithAuthorization)**, allowing gasless, off-chain authorized transfers.\n\n---\n\n## ✨ Features\n\n### Core Token Features\n- ✅ **ERC-20** - Standard token interface\n- ✅ **ERC-2612 Permit** - Gasless approvals via signatures\n- ✅ **EIP-3009** - TransferWithAuthorization for x402 compatibility\n- ✅ **6 Decimals** - USDC/x402 convention ($1 = 1,000,000 base units)\n\n### Enterprise Features\n- ✅ **Role-Based Access Control (RBAC)** - 6 roles: Admin, Minter, Burner, Pauser, Blacklister, KYC Manager\n- ✅ **Blacklist** - Compliance and regulatory requirements\n- ✅ **Pausable** - Emergency stop mechanism\n- ✅ **KYC Registry** - Optional 5-tier KYC level system with configurable daily limits\n- ✅ **Pluggable Identity/AML Gates** - `IIdentityGate` / `IAmlGate` interfaces injected via `setIdentityGate` / `setAmlGate`; the token never knows the concrete verification source (zero address = check skipped). Ships with `SelfRegistryGate` (wraps KYCRegistry), `SelfAmlGate` (self-issued expiring AML flags), and test mocks. Enforcement stays in `_transfer` on-chain — EIP-3009 is permissionless, so facilitator-only checks would be bypassable.\n- ✅ **UUPS Upgradeable** - Safely upgrade contract logic\n- ✅ **Diamond-Ready Storage** - Isolated storage slots for future EIP-2535 migration\n\n---\n\n## 🚀 Installation\n\n### Using npm (Recommended)\n\n```bash\nnpm install @bbuilders/djeon402-contracts\n```\n\n### Using Foundry\n\n> **Note**: Private repo인 경우 GitHub 인증(PAT 토큰)이 필요합니다.\n\n```bash\nforge install b-builders/dongjeon402-contract-sdk\n```\n\nAdd to your `remappings.txt`:\n```\n@bbuilders/djeon402-contracts/=lib/dongjeon402-contract-sdk/\n```\n\n---\n\n## 🎯 Quick Start\n\n### 1. Simplest Token (Just Inherit)\n\n```solidity\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport \"@bbuilders/djeon402-contracts/src/DONGJEON402.sol\";\n\ncontract MyToken is DONGJEON402 {\n    // That's it! All features inherited:\n    // - ERC-20 with 6 decimals (USDC/x402 convention)\n    // - Gasless transfers (EIP-3009)\n    // - Permit (ERC-2612)\n    // - RBAC, Blacklist, Pausable\n    // - UUPS upgradeable\n}\n```\n\n### 2. Deploy with Proxy\n\n```solidity\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport \"@bbuilders/djeon402-contracts/src/DONGJEON402.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\ncontract DeployMyToken {\n    function deploy() external returns (address) {\n        // Step 1: Deploy implementation\n        DONGJEON402 implementation = new DONGJEON402();\n\n        // Step 2: Encode initialization data\n        bytes memory initData = abi.encodeWithSelector(\n            DONGJEON402.initialize.selector,\n            msg.sender,        // admin address\n            \"My Token\",        // token name\n            \"MTK\"              // token symbol\n        );\n\n        // Step 3: Deploy proxy\n        ERC1967Proxy proxy = new ERC1967Proxy(\n            address(implementation),\n            initData\n        );\n\n        // Step 4: Return proxy address (this is your token address)\n        return address(proxy);\n    }\n}\n```\n\n### 3. Use the Token\n\n```solidity\n// Wrap proxy as DONGJEON402 interface\nDONGJEON402 token = DONGJEON402(proxyAddress);\n\n// Mint tokens (requires MINTER_ROLE)\ntoken.mint(user, 1000 * 10**6); // 1000 tokens (6 decimals)\n\n// Standard ERC-20 transfers\ntoken.transfer(recipient, 100 * 10**6);\n\n// Gasless transfer with signature (x402 compatible)\ntoken.transferWithAuthorization(\n    from,\n    to,\n    amount,\n    validAfter,\n    validBefore,\n    nonce,\n    v, r, s\n);\n\n// Pause in emergency (requires PAUSER_ROLE)\ntoken.pause();\n```\n\n---\n\n## 📚 Examples\n\nSee the [`examples/`](./examples) directory for complete working examples:\n\n### 1. **BasicToken.sol**\nThe simplest possible implementation - just inherit DONGJEON402.\n\n```solidity\nimport \"@bbuilders/djeon402-contracts/src/DONGJEON402.sol\";\n\ncontract BasicToken is DONGJEON402 {\n    // Ready to use!\n}\n```\n\n### 2. **CustomToken.sol** ⭐ Recommended for Custom Tokens\nDeploy custom tokens with configurable name, symbol, and initial supply.\n\n```solidity\nCustomTokenDeployer deployer = new CustomTokenDeployer();\n\n// Deploy fully custom token\naddress token = deployer.deployCustomToken(\n    admin,\n    \"My Token\",    // custom name\n    \"MTK\",         // custom symbol\n    1000000        // 1M tokens initial supply\n);\n\n// Or use pre-configured examples\naddress usds = deployer.deployUSDStablecoin(admin);      // USD Stablecoin\naddress krws = deployer.deployKRWStablecoin(admin);      // Korean Won\naddress eurs = deployer.deployEuroStablecoin(admin);     // Euro\n```\n\n### 3. **StablecoinWithInitialSupply.sol**\nMint initial supply during deployment.\n\n```solidity\ncontract MyStablecoin is DONGJEON402 {\n    function initializeWithSupply(\n        address admin,\n        string memory name,\n        string memory symbol,\n        uint256 initialSupply\n    ) public initializer {\n        initialize(admin, name, symbol);\n        _mint(admin, initialSupply);\n    }\n}\n```\n\n### 4. **RewardToken.sol**\nAutomatically give 1% rewards on every transfer.\n\n```solidity\ncontract RewardToken is DONGJEON402 {\n    uint256 public rewardRate = 100; // 1%\n\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual override {\n        super._afterTokenTransfer(from, to, amount);\n\n        if (from != address(0) && to != address(0)) {\n            uint256 reward = (amount * rewardRate) / 10000;\n            if (reward > 0) _mint(to, reward);\n        }\n    }\n}\n```\n\n### 5. **DeployExample.sol**\nComplete deployment example with UUPS proxy pattern.\n\nSee [`examples/`](./examples) directory for all examples and [`examples/README.md`](./examples/README.md) for detailed usage instructions.\n\n---\n\n## 📖 API Reference\n\n### Core Functions\n\n#### `initialize(address admin, string name, string symbol)`\nInitialize the contract (called once during deployment via proxy).\n\n```solidity\nfunction initialize(\n    address admin,\n    string memory name,\n    string memory symbol\n) external initializer\n```\n\n#### Standard ERC-20\n\n```solidity\nfunction name() external view returns (string)\nfunction symbol() external view returns (string)\nfunction decimals() external view returns (uint8)  // Returns 6\nfunction totalSupply() external view returns (uint256)\nfunction balanceOf(address account) external view returns (uint256)\nfunction transfer(address to, uint256 amount) external returns (bool)\nfunction approve(address spender, uint256 amount) external returns (bool)\nfunction transferFrom(address from, address to, uint256 amount) external returns (bool)\nfunction allowance(address owner, address spender) external view returns (uint256)\n```\n\n#### ERC-2612 Permit (Gasless Approvals)\n\n```solidity\nfunction permit(\n    address owner,\n    address spender,\n    uint256 value,\n    uint256 deadline,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n) external\n```\n\n#### EIP-3009 (x402 Protocol)\n\n```solidity\n// Anyone can execute (relayer pays gas)\nfunction transferWithAuthorization(\n    address from,\n    address to,\n    uint256 value,\n    uint256 validAfter,\n    uint256 validBefore,\n    bytes32 nonce,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n) external\n\n// Only the receiver (to == msg.sender) can execute\nfunction receiveWithAuthorization(\n    address from,\n    address to,\n    uint256 value,\n    uint256 validAfter,\n    uint256 validBefore,\n    bytes32 nonce,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n) external\n\n// Cancel an unused authorization (marks nonce as used)\nfunction cancelAuthorization(\n    address authorizer,\n    bytes32 nonce,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n) external\n\n// Check if a nonce has been used\nfunction authorizationState(\n    address authorizer,\n    bytes32 nonce\n) external view returns (bool)\n```\n\n### Admin Functions\n\n#### Minting & Burning\n\n```solidity\nfunction mint(address to, uint256 amount) external onlyRole(MINTER_ROLE)\nfunction burn(uint256 amount) external onlyRole(BURNER_ROLE)\n```\n\n#### Pause/Unpause\n\n```solidity\nfunction pause() external onlyRole(PAUSER_ROLE)\nfunction unpause() external onlyRole(PAUSER_ROLE)\nfunction paused() external view returns (bool)\n```\n\n#### Blacklist\n\n```solidity\nfunction blacklist(address account) external onlyRole(BLACKLISTER_ROLE)\nfunction unBlacklist(address account) external onlyRole(BLACKLISTER_ROLE)\nfunction isBlacklisted(address account) external view returns (bool)\n```\n\n#### Role Management\n\n```solidity\nbytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\nbytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\nbytes32 public constant BURNER_ROLE = keccak256(\"BURNER_ROLE\");\nbytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\nbytes32 public constant BLACKLISTER_ROLE = keccak256(\"BLACKLISTER_ROLE\");\nbytes32 public constant KYC_MANAGER_ROLE = keccak256(\"KYC_MANAGER_ROLE\");\n\nfunction hasRole(bytes32 role, address account) external view returns (bool)\nfunction grantRole(bytes32 role, address account) external onlyRole(DEFAULT_ADMIN_ROLE)\nfunction revokeRole(bytes32 role, address account) external onlyRole(DEFAULT_ADMIN_ROLE)\nfunction renounceRole(bytes32 role, address account) external\n```\n\n#### KYC Registry\n\n**KYC Levels:**\n\n| Level | Name  | Default Daily Limit |\n|-------|-------|-------------------|\n| 0     | None  | $0 (no access)    |\n| 1     | Tier1 | $1,000            |\n| 2     | Tier2 | $10,000           |\n| 3     | Tier3 | $1,000,000        |\n| 4     | Tier4 | Unlimited         |\n\n> Daily limits are configurable by admin via `setLevelLimit()`. Defaults are set on deployment.\n\n```solidity\n// KYC Management (admin only)\nfunction verifyKYC(address user, KYCLevel level, uint256 expiryDate, string kycHash) external onlyKYCAdmin\nfunction updateKYC(address user, KYCLevel level, uint256 expiryDate) external onlyKYCAdmin\nfunction revokeKYC(address user) external onlyKYCAdmin\n\n// Level Limit Configuration (admin only)\nfunction setLevelLimit(KYCLevel level, uint256 newLimit) external onlyKYCAdmin\nfunction setDailyLimit(address user, uint256 newLimit) external onlyKYCAdmin\n\n// View Functions\nfunction getLevelLimit(KYCLevel level) external view returns (uint256)\nfunction getKYCData(address user) external view returns (KYCLevel, uint256, string, bool, uint256, uint256)\nfunction getKYCLevel(address user) external view returns (KYCLevel)\nfunction isKYCValid(address user) external view returns (bool)\nfunction getRemainingDailyLimit(address user) external view returns (uint256)\nfunction checkDailyLimit(address user, uint256 amount) external returns (bool)\n```\n\n#### Identity / AML Gates (pluggable compliance sources)\n\nThe token enforces two independent compliance axes in `_transfer`, each behind\nan interface it is injected with — the token never knows the concrete source:\n\n- `IIdentityGate` — per-person verification: `isVerified(address)`, `levelOf(address)`\n- `IAmlGate` — per-address screening: `status(address) returns (bool cleared, uint64 expiry)`\n  (expiry is mandatory; a past expiry reverts with `AmlExpired`)\n\nA zero gate address skips that check, so existing deployments keep working\nunchanged. Checks apply to the sender (`from`) and revert with\n`IdentityNotVerified` / `IdentityLevelTooLow` / `AmlNotCleared` / `AmlExpired`.\nEnforcement stays on-chain because EIP-3009 is permissionless — facilitator-only\nchecks could be bypassed by submitting `transferWithAuthorization` directly.\n\n```solidity\n// Gate wiring (admin only) — sources are swappable without token changes\nfunction setIdentityGate(address gate) external onlyRole(DEFAULT_ADMIN_ROLE)\nfunction setAmlGate(address gate) external onlyRole(DEFAULT_ADMIN_ROLE)\nfunction setMinIdentityLevel(uint8 level) external onlyRole(DEFAULT_ADMIN_ROLE)\n\n// View Functions\nfunction getIdentityGate() external view returns (address)\nfunction getAmlGate() external view returns (address)\nfunction getMinIdentityLevel() external view returns (uint8)\n```\n\nBundled implementations (self/mock only — external sources implement the\ninterfaces in their own repositories and get injected by address):\n\n| Contract | Implements | Purpose |\n|----------|-----------|---------|\n| `SelfRegistryGate` | `IIdentityGate` | Wraps the bundled KYCRegistry (default/local source) |\n| `SelfAmlGate` | `IAmlGate` | Self-issued AML flags; `SCREENER_ROLE` sets `(cleared, expiry)` — result only, no PII |\n| `MockIdentityGate` / `MockAmlGate` | both | Test/demo rejection scenarios |\n\nDeployment wiring lives in `script/DeployGates.s.sol` (`DeployLocalGates` for\nlocal, `LinkTokenGates` with `IDENTITY_GATE_ADDRESS` / `AML_GATE_ADDRESS` env\nparams for production).\n\n**Self-hosted verification (no external service)** — the bundled gates make\nthe token fully self-sufficient: identity comes from your own KYCRegistry and\nAML flags are self-issued. This is the default local wiring\n(`DeployLocalGates`) and a production-ready fallback:\n\n```solidity\n// 1. Wire the self-hosted sources (admin)\nSelfRegistryGate identityGate = new SelfRegistryGate(address(kycRegistry));\nSelfAmlGate amlGate = new SelfAmlGate(admin);\ntoken.setIdentityGate(address(identityGate));\ntoken.setAmlGate(address(amlGate));\ntoken.setMinIdentityLevel(2); // require Tier2+\n\n// 2. Verify users through your own registry (KYC admin)\nkycRegistry.verifyKYC(user, KYCStorage.KYCLevel.Tier2, expiry, kycHash);\n\n// 3. Issue AML clearance (screener; expiry is mandatory)\namlGate.setStatus(user, true, uint64(block.timestamp + 30 days));\n\n// user can now transfer; unverified/expired accounts revert on-chain\n```\n\nLater, swapping to any external source is one call — no token change:\n`token.setIdentityGate(externalGateAddress)`.\n\n**Example external adapters** — illustration only. Adapters for concrete\nservices live in their own repositories and get injected by address; this\npackage intentionally ships none of them. Because both interfaces are two\nsmall view functions, a typical adapter is ~15 lines:\n\n```solidity\n// Identity via Quadrata Passport (passport attributes on-chain)\ncontract QuadrataGate is IIdentityGate {\n    IQuadrataReader public immutable reader; // Quadrata's attribute reader\n\n    function isVerified(address account) external view returns (bool) {\n        return reader.hasPassport(account); // KYC'd passport holder\n    }\n\n    function levelOf(address account) external view returns (uint8) {\n        // map e.g. Quadrata AML risk band / country tier to your levels\n        return reader.riskScore(account) <= 5 ? 2 : 1;\n    }\n}\n```\n\n```solidity\n// Identity via World ID (proof-of-personhood registry)\ncontract WorldIdGate is IIdentityGate {\n    IWorldIdRegistry public immutable registry; // your verified-nullifier registry\n\n    function isVerified(address account) external view returns (bool) {\n        return registry.isRegistered(account); // proved personhood once, on-chain\n    }\n\n    function levelOf(address account) external view returns (uint8) {\n        return registry.isRegistered(account) ? 1 : 0; // single-level source\n    }\n}\n```\n\n```solidity\n// Identity via Coinbase Verifications (on-chain verification records on Base)\ncontract CoinbaseVerificationsGate is IIdentityGate {\n    ICoinbaseIndexer public immutable indexer;      // Coinbase's public indexer on Base\n    bytes32 public immutable verifiedAccountSchema; // \"verified account\" record type\n    bytes32 public immutable verifiedCountrySchema; // \"verified country\" record type\n\n    function isVerified(address account) external view returns (bool) {\n        return indexer.hasActiveRecord(account, verifiedAccountSchema);\n    }\n\n    function levelOf(address account) external view returns (uint8) {\n        // country-verified accounts get a higher tier than account-only\n        if (indexer.hasActiveRecord(account, verifiedCountrySchema)) return 2;\n        return indexer.hasActiveRecord(account, verifiedAccountSchema) ? 1 : 0;\n    }\n}\n```\n\n```solidity\n// AML via Chainalysis Sanctions Oracle (free public on-chain oracle)\ncontract SanctionsOracleGate is IAmlGate {\n    ISanctionsList public immutable oracle; // isSanctioned(address)\n    uint64 public constant TTL = 1 days;    // oracle is continuously updated,\n                                            // so clearance is short-lived\n    function status(address account) external view returns (bool, uint64) {\n        bool cleared = !oracle.isSanctioned(account);\n        return (cleared, uint64(block.timestamp) + TTL);\n    }\n}\n```\n\nFor API-based screeners (TRM, Elliptic, …) no new contract is needed: run an\noff-chain worker that screens addresses and pushes results into `SelfAmlGate`\nvia `setStatus(account, cleared, expiry)` with the `SCREENER_ROLE`.\n\n#### Upgradeability (UUPS)\n\n```solidity\nfunction upgradeToAndCall(address newImplementation, bytes data) external onlyRole(DEFAULT_ADMIN_ROLE)\nfunction proxiableUUID() external view returns (bytes32)\n```\n\n---\n\n## 🏗️ Architecture\n\n### Storage Layout (Diamond-Ready)\n\nDONGJEON402 uses isolated storage slots to enable future migration to EIP-2535 (Diamond Standard):\n\n```solidity\nsrc/\n├── DONGJEON402.sol              # Main contract\n├── storage/\n│   ├── TokenStorage.sol         # balances, allowances, supply\n│   ├── PermitStorage.sol        # nonces, DOMAIN_SEPARATOR\n│   ├── AuthorizationStorage.sol # authorization states\n│   ├── AccessStorage.sol        # roles\n│   ├── BlacklistStorage.sol     # blacklisted addresses\n│   ├── PausableStorage.sol      # paused state\n│   └── KYCStorage.sol           # KYC levels\n└── interfaces/\n    └── IERC3009.sol             # EIP-3009 interface\n```\n\nEach storage contract defines its own namespace to prevent collisions:\n\n```solidity\nlibrary TokenStorage {\n    bytes32 constant STORAGE_SLOT = keccak256(\"dongjeon402.storage.token\");\n\n    struct Layout {\n        mapping(address => uint256) balances;\n        mapping(address => mapping(address => uint256)) allowances;\n        uint256 totalSupply;\n        string name;\n        string symbol;\n    }\n}\n```\n\n### Proxy Pattern (UUPS)\n\n```\nUser → ERC1967Proxy → DONGJEON402 Implementation\n                       ↓\n                   Storage (in Proxy)\n```\n\n- All state is stored in the **proxy contract**\n- Implementation contract contains **logic only**\n- Upgrades change the implementation address in the proxy\n- User always interacts with the **same proxy address**\n\n---\n\n## 🔒 Security\n\n### Audits\n\n- Based on **OpenZeppelin Contracts** (industry standard)\n- Custom storage patterns reviewed for upgrade safety\n- UUPS upgrade pattern prevents unauthorized upgrades\n\n### Best Practices\n\n1. **Always deploy via proxy** - Direct deployment of DONGJEON402 should only be used as implementation\n2. **Secure admin keys** - Admin role can upgrade contract, mint, pause\n3. **Test upgrades** - Use `forge test` to verify upgrade compatibility\n4. **Monitor events** - All critical actions emit events\n5. **Use multi-sig** - Consider using Gnosis Safe for admin role\n\n### Known Limitations\n\n- 6 decimals (USDC/x402 convention; matches ComplianceRegistry/KYCRegistry limit units, set during initialization)\n- UUPS upgrades require admin role\n- Blacklisted addresses cannot transfer or receive\n\n---\n\n## 🛠️ Development\n\n### Build\n\n```bash\nforge build\n```\n\n### Test\n\n```bash\nforge test\n```\n\n### Deploy\n\nRefer to the [`examples/DeployExample.sol`](./examples/DeployExample.sol) for deployment patterns, or create your own deployment script:\n\n```bash\n# Create your deployment script\nforge script script/YourDeploy.s.sol --rpc-url <RPC_URL> --broadcast\n```\n\n---\n\n## 📦 Package Contents\n\n```\ndongjeon402-contract-sdk/\n├── src/\n│   ├── DONGJEON402.sol           # Main contract\n│   ├── KYCRegistry.sol           # Optional KYC registry\n│   ├── interfaces/               # Contract interfaces\n│   │   └── IERC3009.sol\n│   └── storage/                  # Diamond-ready storage (7 files)\n├── examples/                     # 5 usage examples\n│   ├── BasicToken.sol\n│   ├── CustomToken.sol           # ⭐ NEW - Custom tokens\n│   ├── StablecoinWithInitialSupply.sol\n│   ├── RewardToken.sol\n│   └── DeployExample.sol\n├── lib/                          # Foundry dependencies\n├── foundry.toml                  # Foundry config\n├── remappings.txt                # Import remappings\n└── package.json                  # npm config\n```\n\n---\n\n## 🤝 Contributing\n\nContributions welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new features\n4. Ensure `forge test` passes\n5. Submit a pull request\n\n---\n\n## 📄 License\n\nMIT License - see [LICENSE](./LICENSE) file for details.\n\n---\n\n## 🔗 Links\n\n- **GitHub**: (Update with your repository URL)\n- **Examples**: [./examples/](./examples)\n- **NPM**: @bbuilders/djeon402-contracts (when published)\n\n> **Note**: Update URLs in package.json before publishing\n\n---\n\n## 📦 Related Packages\n\n- [@bbuilders/djeon402-core](https://www.npmjs.com/package/@bbuilders/djeon402-core) - Core types and utilities\n- [@bbuilders/djeon402-sdk-node](https://www.npmjs.com/package/@bbuilders/djeon402-sdk-node) - Node.js/Backend SDK\n- [@bbuilders/djeon402-sdk-client](https://www.npmjs.com/package/@bbuilders/djeon402-sdk-client) - Browser/Frontend SDK\n\n---\n\n## 💬 Support\n\n- **Issues**: Create issues in your repository\n- **Documentation**: See [examples/README.md](./examples/README.md) for usage guides\n\n---\n\n**Built with ❤️ for the x402 protocol ecosystem**\n","readmeFilename":"README.md"}