460 lines
11 KiB
Markdown
460 lines
11 KiB
Markdown
# 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
|
|
|
|
```solidity
|
|
// 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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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:
|
|
|
|
```solidity
|
|
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
|
|
|
|
```solidity
|
|
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
|
|
|
|
```javascript
|
|
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
|
|
|
|
```javascript
|
|
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
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
```solidity
|
|
// 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:
|
|
|
|
```solidity
|
|
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:
|
|
|
|
```solidity
|
|
function adminFunction() external {
|
|
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not admin");
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### 3. Reentrancy Protection
|
|
|
|
Use reentrancy guards for state-changing functions:
|
|
|
|
```solidity
|
|
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:
|
|
|
|
```solidity
|
|
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
|
|
|