11 KiB
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
- Always verify contract addresses before interacting
- Check contract state (paused, active, etc.) before operations
- Validate inputs to prevent unexpected behavior
- Use safe math operations (OpenZeppelin SafeMath or Solidity 0.8+)
- Implement access controls for sensitive operations
- Monitor events for important state changes
- Test thoroughly before deploying to mainnet
Last Updated: 2025-12-24