366 lines
9.6 KiB
Markdown
366 lines
9.6 KiB
Markdown
|
|
# eMoney Token Factory (ChainID 138)
|
||
|
|
|
||
|
|
A comprehensive ERC-20 eMoney Token Factory system with policy-controlled transfers, lien enforcement, compliance management, and bridge functionality.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This system enables the deployment and management of restricted ERC-20 tokens on ChainID 138 with the following key features:
|
||
|
|
|
||
|
|
- **Policy-Controlled Transfers**: All transfers are validated through a centralized PolicyManager
|
||
|
|
- **Lien Enforcement**: Two modes supported
|
||
|
|
- **Hard Freeze Mode**: Any active lien blocks all outbound transfers
|
||
|
|
- **Encumbered Mode**: Transfers allowed up to `freeBalance = balance - encumbrance`
|
||
|
|
- **Compliance Registry**: Track account compliance status, risk tiers, and jurisdiction
|
||
|
|
- **Debt Registry**: Multi-lien support with aggregation and priority
|
||
|
|
- **Bridge Vault**: Optional public chain bridge with light client verification
|
||
|
|
- **UUPS Upgradable**: Token implementations use UUPS proxy pattern for upgradeability
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Contract Relationships
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
subgraph "Registry Layer"
|
||
|
|
CR[ComplianceRegistry]
|
||
|
|
DR[DebtRegistry]
|
||
|
|
end
|
||
|
|
|
||
|
|
subgraph "Policy Layer"
|
||
|
|
PM[PolicyManager]
|
||
|
|
end
|
||
|
|
|
||
|
|
subgraph "Token Layer"
|
||
|
|
TF[TokenFactory138]
|
||
|
|
EMT[eMoneyToken]
|
||
|
|
IMPL[eMoneyToken<br/>Implementation]
|
||
|
|
end
|
||
|
|
|
||
|
|
subgraph "Bridge Layer"
|
||
|
|
BV[BridgeVault138]
|
||
|
|
end
|
||
|
|
|
||
|
|
CR -->|checks compliance| PM
|
||
|
|
DR -->|provides lien info| PM
|
||
|
|
PM -->|authorizes transfers| EMT
|
||
|
|
PM -->|authorizes transfers| BV
|
||
|
|
TF -->|deploys| EMT
|
||
|
|
IMPL -->|used by| TF
|
||
|
|
EMT -->|uses| PM
|
||
|
|
EMT -->|uses| DR
|
||
|
|
EMT -->|uses| CR
|
||
|
|
BV -->|uses| PM
|
||
|
|
BV -->|uses| CR
|
||
|
|
|
||
|
|
style CR fill:#e1f5ff
|
||
|
|
style DR fill:#e1f5ff
|
||
|
|
style PM fill:#fff4e1
|
||
|
|
style TF fill:#e8f5e9
|
||
|
|
style EMT fill:#e8f5e9
|
||
|
|
style BV fill:#f3e5f5
|
||
|
|
```
|
||
|
|
|
||
|
|
### Transfer Authorization Flow
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant User
|
||
|
|
participant Token as eMoneyToken
|
||
|
|
participant PM as PolicyManager
|
||
|
|
participant CR as ComplianceRegistry
|
||
|
|
participant DR as DebtRegistry
|
||
|
|
|
||
|
|
User->>Token: transfer(to, amount)
|
||
|
|
Token->>PM: canTransfer(from, to, amount)
|
||
|
|
|
||
|
|
alt Token Paused
|
||
|
|
PM-->>Token: (false, PAUSED)
|
||
|
|
else Account Frozen
|
||
|
|
PM->>CR: isFrozen(from/to)
|
||
|
|
CR-->>PM: true
|
||
|
|
PM-->>Token: (false, FROM_FROZEN/TO_FROZEN)
|
||
|
|
else Not Compliant
|
||
|
|
PM->>CR: isAllowed(from/to)
|
||
|
|
CR-->>PM: false
|
||
|
|
PM-->>Token: (false, FROM_NOT_COMPLIANT/TO_NOT_COMPLIANT)
|
||
|
|
else Bridge Only Mode
|
||
|
|
PM->>PM: check bridge address
|
||
|
|
PM-->>Token: (false, BRIDGE_ONLY)
|
||
|
|
else Lien Check
|
||
|
|
alt Hard Freeze Mode
|
||
|
|
Token->>DR: hasActiveLien(from)
|
||
|
|
DR-->>Token: true
|
||
|
|
Token-->>User: TransferBlocked(LIEN_BLOCK)
|
||
|
|
else Encumbered Mode
|
||
|
|
Token->>DR: activeLienAmount(from)
|
||
|
|
DR-->>Token: encumbrance
|
||
|
|
Token->>Token: freeBalance = balance - encumbrance
|
||
|
|
alt amount > freeBalance
|
||
|
|
Token-->>User: TransferBlocked(INSUFF_FREE_BAL)
|
||
|
|
else
|
||
|
|
Token->>Token: _update(from, to, amount)
|
||
|
|
Token-->>User: Transfer succeeded
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
```
|
||
|
|
|
||
|
|
## Contracts
|
||
|
|
|
||
|
|
### Core Contracts
|
||
|
|
|
||
|
|
1. **TokenFactory138**: Factory contract for deploying new eMoney tokens as UUPS proxies
|
||
|
|
2. **eMoneyToken**: Restricted ERC-20 token with transfer hooks and lien enforcement
|
||
|
|
3. **PolicyManager**: Central rule engine for transfer authorization
|
||
|
|
4. **DebtRegistry**: Lien management and aggregation engine
|
||
|
|
5. **ComplianceRegistry**: Compliance status and freeze management
|
||
|
|
6. **BridgeVault138**: Lock/unlock portal for public chain representation
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
### Prerequisites
|
||
|
|
|
||
|
|
- Foundry (forge, cast, anvil)
|
||
|
|
- OpenZeppelin Contracts v5
|
||
|
|
- Node.js 18+ (for API layer)
|
||
|
|
- pnpm 8+ (package manager for API layer)
|
||
|
|
|
||
|
|
### Setup
|
||
|
|
|
||
|
|
1. Clone the repository
|
||
|
|
2. Install Solidity dependencies:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge install OpenZeppelin/openzeppelin-contracts@v5.0.0
|
||
|
|
forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v5.0.0
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Install API dependencies (if using API layer):
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Install pnpm (if not installed)
|
||
|
|
npm install -g pnpm
|
||
|
|
|
||
|
|
# Install all API dependencies
|
||
|
|
cd api
|
||
|
|
pnpm install
|
||
|
|
```
|
||
|
|
|
||
|
|
See [API Getting Started](api/GETTING_STARTED.md) for detailed API setup instructions.
|
||
|
|
|
||
|
|
3. Build:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge build
|
||
|
|
```
|
||
|
|
|
||
|
|
4. Run tests:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge test
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Environment Variables
|
||
|
|
|
||
|
|
Before deploying, you need to set up environment variables. A template file `.env.example` is provided as a reference.
|
||
|
|
|
||
|
|
#### Required Variables
|
||
|
|
|
||
|
|
- `PRIVATE_KEY`: Private key for deployment (without 0x prefix)
|
||
|
|
- **SECURITY WARNING**: This key will have admin access to deployed contracts
|
||
|
|
- Use a dedicated deployment wallet with minimal funds
|
||
|
|
- Never commit this key to version control
|
||
|
|
|
||
|
|
- `RPC_URL`: RPC endpoint URL for ChainID 138
|
||
|
|
|
||
|
|
#### Post-Deployment Variables (Required for Configure.s.sol)
|
||
|
|
|
||
|
|
Set these after initial deployment:
|
||
|
|
- `COMPLIANCE_REGISTRY`: Address of deployed ComplianceRegistry contract
|
||
|
|
- `POLICY_MANAGER`: Address of deployed PolicyManager contract
|
||
|
|
- `TOKEN_FACTORY`: Address of deployed TokenFactory138 contract
|
||
|
|
|
||
|
|
#### Optional Variables
|
||
|
|
|
||
|
|
- `INFURA_API_KEY`: For Infura RPC endpoints (optional)
|
||
|
|
- `ETHERSCAN_API_KEY`: For contract verification (optional)
|
||
|
|
- `GOVERNANCE_MULTISIG`: Multisig address for governance (production)
|
||
|
|
|
||
|
|
#### Setting Up Environment Variables
|
||
|
|
|
||
|
|
1. Copy the example file:
|
||
|
|
```bash
|
||
|
|
cp .env.example .env
|
||
|
|
```
|
||
|
|
|
||
|
|
2. Edit `.env` and fill in your actual values:
|
||
|
|
```bash
|
||
|
|
# Edit .env file with your editor
|
||
|
|
nano .env # or vim, code, etc.
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Alternatively, export variables directly:
|
||
|
|
```bash
|
||
|
|
export PRIVATE_KEY=<your_private_key>
|
||
|
|
export RPC_URL=<chain_rpc_url>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Security Best Practices:**
|
||
|
|
- Never commit `.env` to version control (it's in `.gitignore`)
|
||
|
|
- Use different keys for development, staging, and production
|
||
|
|
- Rotate keys regularly
|
||
|
|
- Use hardware wallets for production deployments
|
||
|
|
- Store sensitive values in secure key management services
|
||
|
|
|
||
|
|
### Deploying the System
|
||
|
|
|
||
|
|
1. Set up environment variables (see above)
|
||
|
|
|
||
|
|
2. Deploy contracts:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge script script/Deploy.s.sol:DeployScript --rpc-url $RPC_URL --broadcast --verify
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Configure roles and initial settings:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
export COMPLIANCE_REGISTRY=<deployed_address>
|
||
|
|
export POLICY_MANAGER=<deployed_address>
|
||
|
|
export TOKEN_FACTORY=<deployed_address>
|
||
|
|
forge script script/Configure.s.sol:ConfigureScript --rpc-url $RPC_URL --broadcast
|
||
|
|
```
|
||
|
|
|
||
|
|
### Deploying a New Token
|
||
|
|
|
||
|
|
```solidity
|
||
|
|
TokenFactory138 factory = TokenFactory138(factoryAddress);
|
||
|
|
|
||
|
|
ITokenFactory138.TokenConfig memory config = ITokenFactory138.TokenConfig({
|
||
|
|
issuer: issuerAddress,
|
||
|
|
decimals: 18,
|
||
|
|
defaultLienMode: 2, // 1 = hard freeze, 2 = encumbered
|
||
|
|
bridgeOnly: false,
|
||
|
|
bridge: bridgeAddress
|
||
|
|
});
|
||
|
|
|
||
|
|
address token = factory.deployToken("My Token", "MTK", config);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Managing Liens
|
||
|
|
|
||
|
|
```solidity
|
||
|
|
DebtRegistry registry = DebtRegistry(debtRegistryAddress);
|
||
|
|
|
||
|
|
// Place a lien
|
||
|
|
uint256 lienId = registry.placeLien(
|
||
|
|
debtor,
|
||
|
|
1000, // amount
|
||
|
|
0, // expiry (0 = no expiry)
|
||
|
|
1, // priority
|
||
|
|
reasonCode
|
||
|
|
);
|
||
|
|
|
||
|
|
// Reduce a lien
|
||
|
|
registry.reduceLien(lienId, 300); // reduce by 300
|
||
|
|
|
||
|
|
// Release a lien
|
||
|
|
registry.releaseLien(lienId);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Transfer Modes
|
||
|
|
|
||
|
|
#### Mode 1: Hard Freeze
|
||
|
|
When a token is in hard freeze mode (`lienMode = 1`), any active lien on an account blocks all outbound transfers.
|
||
|
|
|
||
|
|
#### Mode 2: Encumbered (Recommended)
|
||
|
|
When a token is in encumbered mode (`lienMode = 2`), accounts can transfer up to their `freeBalance`:
|
||
|
|
- `freeBalance = balanceOf(account) - activeLienAmount(account)`
|
||
|
|
- Transfers exceeding `freeBalance` are blocked with `INSUFF_FREE_BAL` reason code
|
||
|
|
|
||
|
|
## Roles
|
||
|
|
|
||
|
|
- `GOVERNANCE_ADMIN_ROLE`: Root governance (should be multisig)
|
||
|
|
- `TOKEN_DEPLOYER_ROLE`: Deploy new tokens via factory
|
||
|
|
- `POLICY_OPERATOR_ROLE`: Configure token policies (pause, bridgeOnly, lienMode)
|
||
|
|
- `ISSUER_ROLE`: Mint/burn tokens
|
||
|
|
- `ENFORCEMENT_ROLE`: Clawback and forceTransfer
|
||
|
|
- `COMPLIANCE_ROLE`: Update compliance registry
|
||
|
|
- `DEBT_AUTHORITY_ROLE`: Place/reduce/release liens
|
||
|
|
- `BRIDGE_OPERATOR_ROLE`: Authorize bridge unlocks
|
||
|
|
|
||
|
|
## Reason Codes
|
||
|
|
|
||
|
|
All transfer blocks emit a `bytes32` reason code:
|
||
|
|
|
||
|
|
- `OK`: Transfer allowed
|
||
|
|
- `PAUSED`: Token is paused
|
||
|
|
- `FROM_FROZEN` / `TO_FROZEN`: Account is frozen
|
||
|
|
- `FROM_NOT_COMPLIANT` / `TO_NOT_COMPLIANT`: Account not compliant
|
||
|
|
- `LIEN_BLOCK`: Hard freeze mode - lien blocks transfer
|
||
|
|
- `INSUFF_FREE_BAL`: Encumbered mode - insufficient free balance
|
||
|
|
- `BRIDGE_ONLY`: Token in bridge-only mode
|
||
|
|
- `UNAUTHORIZED`: Unauthorized operation
|
||
|
|
- `CONFIG_ERROR`: Configuration error
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
### Run All Tests
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge test
|
||
|
|
```
|
||
|
|
|
||
|
|
### Run Specific Test Suite
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge test --match-contract ComplianceRegistryTest
|
||
|
|
forge test --match-contract DebtRegistryTest
|
||
|
|
forge test --match-contract PolicyManagerTest
|
||
|
|
forge test --match-contract eMoneyTokenTest
|
||
|
|
forge test --match-contract TokenFactoryTest
|
||
|
|
```
|
||
|
|
|
||
|
|
### Run Invariant Tests
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge test --match-contract DebtRegistryInvariants
|
||
|
|
forge test --match-contract TransferInvariants
|
||
|
|
```
|
||
|
|
|
||
|
|
### Run Fuzz Tests
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge test --match-contract DebtRegistryFuzz
|
||
|
|
forge test --match-contract TransferFuzz
|
||
|
|
```
|
||
|
|
|
||
|
|
### Generate Coverage Report
|
||
|
|
|
||
|
|
```bash
|
||
|
|
forge coverage
|
||
|
|
```
|
||
|
|
|
||
|
|
## Security Considerations
|
||
|
|
|
||
|
|
1. **Admin Roles**: All admin roles should be assigned to multisigs in production
|
||
|
|
2. **Timelock**: Consider adding timelock for privileged operations
|
||
|
|
3. **Audits**: External security audit recommended before mainnet deployment
|
||
|
|
4. **Upgrades**: UUPS upgradeability requires careful governance control
|
||
|
|
|
||
|
|
## Documentation
|
||
|
|
|
||
|
|
See [RUNBOOK.md](docs/RUNBOOK.md) for operational procedures including:
|
||
|
|
- Role rotation
|
||
|
|
- Emergency pause procedures
|
||
|
|
- Lien dispute handling
|
||
|
|
- Upgrade procedures
|
||
|
|
- Bridge operator procedures
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
MIT
|
||
|
|
|