# Guide: Adding a New Asset Type

**Audience**: Developers, Protocol Administrators  
**Difficulty**: Intermediate  
**Time**: 2-4 hours

---

## Overview

This guide shows how to extend the Universal Bridge to support a new asset type without modifying core contracts.

> Note: This plugin-handler flow is historical reference material. The original `IAssetTypeHandler` and `PluginRegistry` sources were archived under `archive/solidity/contracts/registry/interfaces/` and `archive/solidity/contracts/plugins/` to keep them out of the active Forge compile graph.

---

## Prerequisites

- Asset type handler contract
- Optional: Specialized bridge contract
- Optional: Liquidity provider for asset
- Governance approval (for regulated assets)

---

## Step-by-Step Process

### Step 1: Create Asset Type Handler

Implement `IAssetTypeHandler` interface:

```solidity
// Historical reference: archive/solidity/contracts/registry/handlers/MyAssetHandler.sol
import "../interfaces/IAssetTypeHandler.sol";

contract MyAssetHandler is IAssetTypeHandler {
    function validateAsset(address token) external view override returns (bool) {
        // Validate token is your asset type
        return token.code.length > 0; // Basic check
    }

    function getRequiredCompliance() external pure override returns (ComplianceLevel) {
        return ComplianceLevel.KYC; // Or Public, Accredited, etc.
    }

    function getDefaultLimits() external pure override returns (uint256 min, uint256 max) {
        return (1e15, 1000000e18); // Min and max bridge amounts
    }

    function preTransferHook(address from, address to, uint256 amount) external override {
        // Pre-transfer validation
    }

    function postTransferHook(address from, address to, uint256 amount) external override {
        // Post-transfer hooks
    }
}
```

### Step 2: Deploy Handler

```bash
# Deploy handler contract
forge create contracts/registry/handlers/MyAssetHandler.sol:MyAssetHandler \
    --rpc-url http://192.168.11.211:8545 \
    --private-key $PRIVATE_KEY
```

### Step 3: Historical PluginRegistry Registration

```solidity
// Register handler as plugin
pluginRegistry.registerPlugin(
    PluginType.AssetTypeHandler,
    keccak256("MyAssetType"),
    0xHandlerAddress,
    "1.0.0",
    "Handler for MyAsset tokens"
);
```

### Step 4: Create Specialized Bridge (Optional)

If your asset needs custom bridge logic:

```solidity
// contracts/bridge/MyAssetCCIPBridge.sol
import "./UniversalCCIPBridge.sol";

contract MyAssetCCIPBridge is UniversalCCIPBridge {
    function bridgeMyAsset(
        address token,
        uint256 amount,
        uint64 destinationChain,
        address recipient,
        bytes calldata customData
    ) external nonReentrant returns (bytes32 messageId) {
        // Custom bridge logic
        
        // Call parent bridge
        BridgeOperation memory op = BridgeOperation({
            token: token,
            amount: amount,
            destinationChain: destinationChain,
            recipient: recipient,
            assetType: bytes32(uint256(AssetType.Custom)),
            usePMM: false,
            useVault: false,
            complianceProof: customData,
            vaultInstructions: ""
        });
        
        return bridge(op);
    }
}
```

### Step 5: Register Bridge with Orchestrator

```solidity
// Register specialized bridge
orchestrator.registerAssetTypeBridge(
    AssetType.MyAssetType,
    0xMyAssetBridgeAddress
);
```

### Step 6: Configure Liquidity (Optional)

If asset should use PMM:

```solidity
// Configure liquidity for asset
liquidityManager.configureAsset(
    0xTokenAddress,
    1000e18,      // minAmountForPMM
    50,           // maxSlippageBps (0.5%)
    300,          // timeout (5 minutes)
    true,         // autoCreate pools
    true          // enabled
);
```

### Step 7: Update Tokenlist

Add to `tokenlist.json`:

```json
{
  "chainId": 138,
  "address": "0xYourTokenAddress",
  "name": "My Asset Token",
  "symbol": "MAT",
  "decimals": 18,
  "assetType": "MyAssetType",
  "complianceLevel": "KYC",
  "tags": ["custom", "experimental"]
}
```

### Step 8: Submit Tokenlist Version

```solidity
// Submit new version with auto-proposal
AssetMetadata[] memory metadata = new AssetMetadata[](1);
metadata[0] = AssetMetadata({
    tokenAddress: 0xYourTokenAddress,
    assetType: AssetType.MyAssetType,
    complianceLevel: ComplianceLevel.KYC,
    name: "My Asset Token",
    symbol: "MAT",
    decimals: 18,
    jurisdiction: "US",
    volatilityScore: 50,
    minBridgeAmount: 1e15,
    maxBridgeAmount: 1000000e18
});

bytes32[] memory proposalIds = tokenlistSync.submitTokenlistVersion(
    2, 0, 0,                    // version
    "QmIPFSHash...",            // IPFS hash
    [0xYourTokenAddress],       // new tokens
    metadata                    // metadata
);
```

### Step 9: Governance Approval

If asset requires governance:

```solidity
// Validators vote
registry.voteOnProposal(proposalIds[0], true);

// Wait for timelock
// ... wait 1-7 days based on asset risk ...

// Execute proposal
registry.executeProposal(proposalIds[0]);
```

### Step 10: Verify Asset Registered

```solidity
// Check asset is active
bool isActive = registry.isAssetActive(0xYourTokenAddress);
assert(isActive);

// Get asset info
UniversalAsset memory asset = registry.getAsset(0xYourTokenAddress);
console.log("Asset Type:", uint256(asset.assetType));
console.log("Min Bridge:", asset.minBridgeAmount);
console.log("Max Bridge:", asset.maxBridgeAmount);
```

---

## Example: Adding Carbon Credits

Let's walk through a complete example of adding a new asset type.

### 1. Create Handler

```solidity
// contracts/registry/handlers/CarbonCreditHandler.sol
contract CarbonCreditHandler is IAssetTypeHandler {
    ICarbonRegistry public carbonRegistry;
    
    function validateAsset(address token) external view override returns (bool) {
        return carbonRegistry.isValidCredit(token);
    }

    function getRequiredCompliance() external pure override returns (ComplianceLevel) {
        return ComplianceLevel.KYC;
    }

    function getDefaultLimits() external pure override returns (uint256 min, uint256 max) {
        return (1e18, 1000000e18); // 1 to 1M credits
    }

    function preTransferHook(address from, address to, uint256 amount) external override {
        require(carbonRegistry.isVerifiedOwner(from), "Not verified");
        require(amount >= 1e18, "Min 1 credit");
    }

    function postTransferHook(address, address, uint256) external pure override {}
}
```

### 2. Create Specialized Bridge

```solidity
// contracts/bridge/CarbonCreditCCIPBridge.sol
contract CarbonCreditCCIPBridge is UniversalCCIPBridge {
    ICarbonRegistry public carbonRegistry;
    
    mapping(bytes32 => string) public creditCertificates;
    
    function bridgeCarbonCredit(
        address token,
        uint256 amount,
        uint64 destinationChain,
        address recipient,
        string calldata certificateURI
    ) external nonReentrant returns (bytes32 messageId) {
        // Verify carbon credit validity
        require(carbonRegistry.isValidCredit(token), "Invalid credit");
        require(carbonRegistry.hasValidCertificate(token, certificateURI), "Invalid certificate");
        
        // Execute bridge
        BridgeOperation memory op = BridgeOperation({
            token: token,
            amount: amount,
            destinationChain: destinationChain,
            recipient: recipient,
            assetType: bytes32(uint256(11)), // Custom type ID
            usePMM: true,
            useVault: false,
            complianceProof: abi.encode(certificateURI),
            vaultInstructions: ""
        });
        
        messageId = bridge(op);
        creditCertificates[messageId] = certificateURI;
        
        return messageId;
    }
}
```

### 3. Deploy and Register

```bash
# 1. Deploy handler
HANDLER=$(forge create contracts/registry/handlers/CarbonCreditHandler.sol:CarbonCreditHandler --rpc-url ... | grep "Deployed to:" | awk '{print $3}')

# 2. Deploy bridge
BRIDGE=$(forge create contracts/bridge/CarbonCreditCCIPBridge.sol:CarbonCreditCCIPBridge --rpc-url ... | grep "Deployed to:" | awk '{print $3}')

# 3. Register handler
cast send $PLUGIN_REGISTRY "registerPlugin(uint8,bytes32,address,string,string)" \
    0 \
    $(cast keccak "CarbonCredit") \
    $HANDLER \
    "1.0.0" \
    "Carbon credit handler" \
    --private-key $PRIVATE_KEY

# 4. Register bridge
cast send $ORCHESTRATOR "registerAssetTypeBridge(uint8,address)" \
    11 \
    $BRIDGE \
    --private-key $PRIVATE_KEY
```

### 4. Add to Tokenlist

```json
{
  "chainId": 138,
  "address": "0xCarbonCreditToken",
  "name": "Verified Carbon Credits",
  "symbol": "VCC",
  "decimals": 18,
  "assetType": "CarbonCredit",
  "complianceLevel": "KYC",
  "jurisdiction": "Global",
  "tags": ["environmental", "carbon", "esg"]
}
```

### 5. Submit and Approve

```typescript
// Submit tokenlist version
const tx = await tokenlistSync.submitTokenlistVersion(
    2, 1, 0,
    "QmNewHash...",
    ["0xCarbonCreditToken"],
    [carbonCreditMetadata]
);

// Validators vote...
// Timelock passes...
// Execute proposal...

console.log("Carbon credits now bridgeable!");
```

---

## Best Practices

### DO:
- Test on testnet first
- Document asset-specific requirements
- Set appropriate risk parameters
- Configure reasonable limits
- Enable compliance modules
- Monitor initial transactions

### DON'T:
- Skip governance for regulated assets
- Set limits too high initially
- Ignore compliance requirements
- Forget to test specialized bridge
- Deploy without security review

---

## Troubleshooting

**"Asset not active"**
- Ensure governance proposal executed
- Check asset registration status

**"Destination not enabled"**
- Add destination via bridge.addDestination()

**"Compliance check failed"**
- Verify KYC status if required
- Check jurisdiction restrictions

**"Bridge call failed"**
- Verify specialized bridge is registered
- Check orchestrator routing configuration

---

## Support

- Documentation: https://docs.your-project.io
- Discord: https://discord.gg/your-project
- Forum: https://forum.your-project.io

---

**Last Updated**: 2026-01-24
