Files
explorer-monorepo/docs/INTEGRATION_GUIDES.md

11 KiB

Integration Guides

Date: 2025-12-24
Status: Complete integration guides for all contracts


Overview

This document provides integration guides for developers who want to integrate with the deployed contracts.


Integration with Compliant Tokens

Using CompliantUSDT or CompliantUSDC

1. Import the Contract Interface

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../tokens/CompliantUSDT.sol";

contract MyContract {
    IERC20 public usdt;
    
    constructor(address usdtAddress) {
        usdt = IERC20(usdtAddress);
    }
    
    function transferUSDT(address to, uint256 amount) external {
        usdt.transfer(to, amount);
    }
}

2. Handle Pausable State

import "@openzeppelin/contracts/security/Pausable.sol";
import "../tokens/CompliantUSDT.sol";

contract MyContract {
    CompliantUSDT public usdt;
    
    function transferUSDT(address to, uint256 amount) external {
        require(!usdt.paused(), "USDT is paused");
        usdt.transfer(to, amount);
    }
}

3. Listen to Compliance Events

contract MyContract {
    event ValueTransferDetected(
        address indexed from,
        address indexed to,
        uint256 value,
        bytes32 legalReferenceHash
    );
    
    function onValueTransferDeclared(
        address from,
        address to,
        uint256 value,
        bytes32 legalReferenceHash
    ) external {
        emit ValueTransferDetected(from, to, value, legalReferenceHash);
    }
}

Integration with TokenRegistry

1. Query Token Information

import "../utils/TokenRegistry.sol";

contract MyContract {
    TokenRegistry public tokenRegistry;
    
    constructor(address registryAddress) {
        tokenRegistry = TokenRegistry(registryAddress);
    }
    
    function getTokenInfo(address token) external view returns (TokenRegistry.TokenInfo memory) {
        return tokenRegistry.getTokenInfo(token);
    }
    
    function isTokenActive(address token) external view returns (bool) {
        return tokenRegistry.isTokenActive(token);
    }
    
    function findTokenBySymbol(string calldata symbol) external view returns (address) {
        return tokenRegistry.getTokenBySymbol(symbol);
    }
}

2. Register Your Token

contract MyToken {
    TokenRegistry public tokenRegistry;
    
    constructor(address registryAddress) {
        tokenRegistry = TokenRegistry(registryAddress);
    }
    
    function registerInRegistry() external {
        // This should be called by the token registry owner
        tokenRegistry.registerToken(
            address(this),
            "My Token",
            "MTK",
            18,
            false, // not native
            address(0) // not bridged
        );
    }
}

Integration with FeeCollector

1. Collect Fees

import "../utils/FeeCollector.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract MyContract {
    FeeCollector public feeCollector;
    IERC20 public feeToken;
    
    constructor(address collectorAddress, address tokenAddress) {
        feeCollector = FeeCollector(collectorAddress);
        feeToken = IERC20(tokenAddress);
    }
    
    function collectFees(uint256 amount) external {
        // Approve first
        feeToken.approve(address(feeCollector), amount);
        
        // Collect fees
        feeCollector.collectFees(address(feeToken), amount);
    }
    
    function collectETHFees() external payable {
        feeCollector.collectFees{value: msg.value}(address(0), msg.value);
    }
}

2. Query Fee Information

contract MyContract {
    FeeCollector public feeCollector;
    
    function getFeeStats(address token) external view returns (
        uint256 totalCollected,
        uint256 totalDistributed,
        uint256 currentBalance
    ) {
        totalCollected = feeCollector.getTotalCollected(token);
        totalDistributed = feeCollector.getTotalDistributed(token);
        currentBalance = feeCollector.getBalance(token);
    }
}

Integration with ComplianceRegistry

1. Check Contract Compliance

import "../compliance/ComplianceRegistry.sol";

contract MyContract {
    ComplianceRegistry public complianceRegistry;
    
    constructor(address registryAddress) {
        complianceRegistry = ComplianceRegistry(registryAddress);
    }
    
    function isContractCompliant(address contractAddress) external view returns (bool) {
        return complianceRegistry.isContractRegistered(contractAddress);
    }
    
    function getComplianceInfo(address contractAddress) external view returns (
        bool isRegistered,
        string memory frameworkVersion,
        string memory jurisdiction
    ) {
        ComplianceRegistry.ContractComplianceStatus memory status = 
            complianceRegistry.getContractComplianceStatus(contractAddress);
        
        return (
            status.isRegistered,
            status.legalFrameworkVersion,
            status.legalJurisdiction
        );
    }
}

2. Register Your Contract

If your contract inherits from LegallyCompliantBase, it can be registered:

import "../compliance/LegallyCompliantBase.sol";
import "../compliance/ComplianceRegistry.sol";

contract MyCompliantContract is LegallyCompliantBase {
    ComplianceRegistry public complianceRegistry;
    
    constructor(address admin, address registryAddress) LegallyCompliantBase(admin) {
        complianceRegistry = ComplianceRegistry(registryAddress);
    }
    
    function registerSelf() external {
        // This should be called by the registry owner
        complianceRegistry.registerContract(address(this));
    }
}

Integration with AddressMapper

1. Map Addresses

import "../utils/AddressMapper.sol";

contract MyContract {
    AddressMapper public addressMapper;
    
    constructor(address mapperAddress) {
        addressMapper = AddressMapper(mapperAddress);
    }
    
    function getActualAddress(address genesisAddress) external view returns (address) {
        return addressMapper.getDeployedAddress(genesisAddress);
    }
    
    function checkIfMapped(address addr) external view returns (bool) {
        return addressMapper.isMapped(addr);
    }
}

Frontend Integration

1. Web3.js Integration

const { ethers } = require('ethers');

// Connect to provider
const provider = new ethers.providers.JsonRpcProvider('http://192.168.11.250:8545');

// Get contract instance
const usdtAbi = [...]; // ABI from contract
const usdtAddress = '0x...'; // Deployed address
const usdt = new ethers.Contract(usdtAddress, usdtAbi, provider);

// Read operations
const balance = await usdt.balanceOf(userAddress);
const totalSupply = await usdt.totalSupply();
const isPaused = await usdt.paused();

// Write operations (need signer)
const signer = provider.getSigner();
const usdtWithSigner = usdt.connect(signer);
const tx = await usdtWithSigner.transfer(recipientAddress, amount);
await tx.wait();

2. Ethers.js Integration

import { ethers } from 'ethers';

// Connect to provider
const provider = new ethers.JsonRpcProvider('http://192.168.11.250:8545');

// Get contract instance
const tokenRegistryAbi = [...]; // ABI
const tokenRegistryAddress = '0x...';
const registry = new ethers.Contract(tokenRegistryAddress, tokenRegistryAbi, provider);

// Query token info
const tokenInfo = await registry.getTokenInfo(tokenAddress);
const allTokens = await registry.getAllTokens();
const tokenCount = await registry.getTokenCount();

3. Event Listening

// Listen to ValueTransferDeclared events
usdt.on('ValueTransferDeclared', (from, to, value, legalRefHash, event) => {
    console.log('Value transfer:', {
        from,
        to,
        value: value.toString(),
        legalRefHash,
        blockNumber: event.blockNumber
    });
});

// Listen to TokenRegistered events
registry.on('TokenRegistered', (tokenAddress, name, symbol, decimals, event) => {
    console.log('Token registered:', {
        tokenAddress,
        name,
        symbol,
        decimals,
        blockNumber: event.blockNumber
    });
});

Testing Integration

1. Foundry Tests

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

import "forge-std/Test.sol";
import "../tokens/CompliantUSDT.sol";
import "../utils/TokenRegistry.sol";

contract IntegrationTest is Test {
    CompliantUSDT public usdt;
    TokenRegistry public registry;
    
    function setUp() public {
        usdt = new CompliantUSDT(address(this), address(this));
        registry = new TokenRegistry(address(this));
    }
    
    function testTokenRegistration() public {
        registry.registerToken(
            address(usdt),
            "Tether USD (Compliant)",
            "cUSDT",
            6,
            false,
            address(0)
        );
        
        assertTrue(registry.isTokenRegistered(address(usdt)));
        assertTrue(registry.isTokenActive(address(usdt)));
    }
    
    function testTokenTransfer() public {
        address recipient = address(0x123);
        uint256 amount = 1000 * 10**6;
        
        usdt.transfer(recipient, amount);
        
        assertEq(usdt.balanceOf(recipient), amount);
    }
}

Best Practices

1. Error Handling

Always check return values and handle errors:

function safeTransfer(address token, address to, uint256 amount) external {
    IERC20(token).transfer(to, amount);
    // Check if transfer was successful
    require(IERC20(token).balanceOf(to) >= amount, "Transfer failed");
}

2. Access Control

Always verify access control:

function adminFunction() external {
    require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not admin");
    // ...
}

3. Reentrancy Protection

Use reentrancy guards for state-changing functions:

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract MyContract is ReentrancyGuard {
    function withdraw() external nonReentrant {
        // Safe withdrawal logic
    }
}

4. Event Emission

Always emit events for important state changes:

event TokenTransferred(address indexed from, address indexed to, uint256 amount);

function transfer(address to, uint256 amount) external {
    // Transfer logic
    emit TokenTransferred(msg.sender, to, amount);
}

Security Considerations

  1. Always verify contract addresses before interacting
  2. Check contract state (paused, active, etc.) before operations
  3. Validate inputs to prevent unexpected behavior
  4. Use safe math operations (OpenZeppelin SafeMath or Solidity 0.8+)
  5. Implement access controls for sensitive operations
  6. Monitor events for important state changes
  7. Test thoroughly before deploying to mainnet

Last Updated: 2025-12-24