> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trusset.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration

> Deployment sequence, configuration, and connecting the Commodity Token suite to your infrastructure.

This page covers the end-to-end deployment and configuration of the Commodity Token License contracts. The deployment sequence matters - contracts reference each other and must be deployed in the correct order.

## Deployment Sequence

<Steps>
  <Step title="Deploy the Identity Registry">
    Deploy `IdentityRegistryUpgradeable` as a UUPS proxy. Initialize with your Gnosis Safe multisig as `gnosisSafe` (receives `DEFAULT_ADMIN_ROLE`) and a named legal entity as `legalOperator` (receives `LEGAL_OPERATOR_ROLE`, required by BaFin for upgrade authorization).

    After initialization, grant roles:

    * `KYC_PROVIDER_ROLE` to your licensed KYC service via `addKYCProvider(address, name)`
    * `REGISTER_OPERATOR_ROLE` to your register operator via `addRegisterOperator(address, name)`
    * `COMPLIANCE_ROLE` to your compliance officer(s) via `addComplianceOfficer(address)`
  </Step>

  <Step title="Deploy the Token Implementation">
    Deploy `CommodityTokenUpgradeable` as a standalone contract (not behind a proxy). This serves as the shared implementation that all token proxies will point to. Do not call `initialize` on the implementation - the constructor calls `_disableInitializers()`.
  </Step>

  <Step title="Deploy the Factory">
    Deploy `CommodityTokenFactoryUpgradeable` as a UUPS proxy. Initialize with:

    * `_identityRegistry` - address from Step 1
    * `_commodityTokenImplementation` - address from Step 2
    * `_admin` - TrussetDAO Gnosis Safe address
    * `_platformWallet` - Trusset treasury address for fee collection
  </Step>

  <Step title="Create Tokens">
    Call `createCommodityToken` or `createSimpleCommodityToken` on the factory. Each call deploys a new `ERC1967Proxy` and initializes the token with its own `mainIssuer`, `gramsPerToken`, `maxSupply`, and compliance settings.

    The `mainIssuer` address receives full operational control. The `upgradeAuthority` is set to the factory's `admin` (TrussetDAO).
  </Step>

  <Step title="Deploy Compliance Module (optional)">
    Deploy `BasicComplianceModule` with the token contract address from Step 4, `defaultMaxHolding` (set `0` for unlimited), and `defaultMinHolding`.

    Register the module on the identity registry via `addComplianceModule(moduleAddress)`.

    <Info>
      `BasicComplianceModule` takes `tokenContract` as an immutable constructor parameter. Deploy it after the token exists, or use deterministic deployment (CREATE2) to predict the token address in advance.
    </Info>
  </Step>

  <Step title="Deploy Sale Infrastructure (optional)">
    Deploy `CommodityTokenSaleFactory` with the platform wallet. Create sale contracts via `createSaleContract(tokenAddress, issuerAddress)`.

    For mint-on-purchase sales, the sale contract must be registered as an authorized minter on the token: call `configureIssuer(saleContractAddress, true, false, 0)` on the token as the main issuer.
  </Step>
</Steps>

## Token Configuration

After deployment, the main issuer (or delegates) should configure the token for their use case.

### Fees

```solidity theme={null}
// Set 1% mint fee and 0.5% burn fee
token.setFees(100, 50);
```

Fees are in basis points. Maximum is 1000 (10%) per operation. The 75/25 split between issuer and platform is fixed at the protocol level.

### KYC and Transfer Restrictions

```solidity theme={null}
// Enable KYC enforcement
token.setKYCConfig(true, identityRegistryAddress);

// Or use whitelist mode instead
token.setTransferRestrictionMode(1); // WHITELIST
token.setWhitelistBatch(addresses, statuses);
```

KYC enforcement and whitelist/blacklist restrictions are independent. You can use both simultaneously - transfers must pass both checks.

### Redemption

```solidity theme={null}
token.setRedemptionConfig(
    true,           // unitsEnabled - require whole-unit redemption
    1000,           // unitWeightGrams - 1kg bars
    100e18,         // minTokensForAsset - minimum 100 tokens for physical
    true,           // cashRedemptionEnabled
    usdcAddress,    // USDC token address
    oracleAddress,  // IPriceOracle implementation
    3600            // maxOracleAge in seconds
);
```

For cash redemption to work, the token contract must hold sufficient USDC. Transfer USDC to the token contract address before enabling cash redemption.

### Sub-Issuers and Delegates

```solidity theme={null}
// Add a delegate (can do most issuer operations)
token.setDelegate(delegateAddress, true);

// Add a sub-issuer with mint authority and a 1M token limit
token.configureIssuer(subIssuerAddress, true, false, 1_000_000e18);
```

Delegates have broad permissions but cannot transfer the main issuer role. Sub-issuers have narrow, configurable permissions with mint caps.

## Price Oracle

The suite expects a price oracle implementing `IPriceOracle`:

```solidity theme={null}
interface IPriceOracle {
    function getPrice() external view returns (
        uint256 price,    // USD price scaled by 10^decimals
        uint8 decimals,   // decimal precision of the price
        uint256 timestamp // last update time
    );
}
```

You must deploy your own oracle implementation or adapt an existing one (e.g., Chainlink). The oracle is used by both the token's cash redemption and the sale contract's dynamic pricing. Staleness is enforced - if `block.timestamp - timestamp > maxOracleAge`, the transaction reverts with `OraclePriceStale`.

## Sale Configuration

### Creating a Sale Round

```solidity theme={null}
saleContract.createSale(
    saleId,             // bytes32 unique identifier
    true,               // mintOnPurchase
    0,                  // fixedPriceUsd (0 = use oracle)
    oracleAddress,      // priceOracle
    usdcAddress,        // paymentToken (address(0) for ETH)
    10e18,              // minPurchase - 10 tokens minimum
    10_000e18,          // maxPurchase per buyer
    1_000_000e18,       // totalAllocation
    200,                // feeBps - 2% sale fee
    block.timestamp,    // startTime
    block.timestamp + 30 days, // endTime
    "ipfs://...",       // metadataUri
    0                   // mintRequestType - INSTANT
);
```

For `mintOnPurchase` sales, ensure the sale contract has minter permissions on the token before the sale starts. For pre-funded sales, call `fundSale(saleId, amount)` after creating the sale round.

### Payment Handling

ETH sales: buyers send ETH with their `purchase` call. The contract forwards payment to the issuer and refunds any excess.

ERC-20 sales: buyers must `approve` the sale contract for the total payment amount (including fees) before calling `purchase`. The contract pulls payment via `safeTransferFrom`.

## Identity Registry Configuration

### Verifying Investors

The KYC provider verifies investors before they can receive or transfer tokens:

```solidity theme={null}
identityRegistry.verifyIdentity(
    userAddress,
    kycHash,           // SHA-256 of off-chain KYC data
    InvestorType.RETAIL,
    uint64(block.timestamp + 365 days), // softExpiry
    uint64(block.timestamp + 730 days)  // hardExpiry
);
```

For onboarding at scale, use `batchVerifyIdentities` (up to 500 per call). The function returns `successCount` and `failedIndices` for partial-failure handling.

### Adding Claims

```solidity theme={null}
identityRegistry.addClaim(
    userAddress,
    ClaimType.ACCREDITATION,
    keccak256(abi.encodePacked(accreditationData)),
    uint64(block.timestamp + 365 days) // expiry, 0 for permanent
);
```

### Compliance Modules

After deploying `BasicComplianceModule`:

```solidity theme={null}
// Register on identity registry
identityRegistry.addComplianceModule(complianceModuleAddress);

// Configure limits (called by the token contract, restricted by onlyToken modifier)
complianceModule.setDefaultLimits(1_000_000e18, 100e18); // max 1M, min 100
complianceModule.setLockup(investorAddress, block.timestamp + 180 days);
```

Custom compliance modules can be built by implementing `IComplianceModule.canTransfer`. Register them on the identity registry alongside or instead of `BasicComplianceModule`.

## Reserve Management

The issuer maintains reserve attestation data on-chain:

```solidity theme={null}
token.updateReserveAttestation(
    totalGrams,         // must satisfy reserve ratio
    vaultLocationHash,  // keccak256 of vault identifier
    "https://..."       // URI to attestation document
);
```

The contract enforces that the new `totalGrams` still satisfies `totalSupply * gramsPerToken <= totalGrams * 1e18`. You cannot decrease reserves below what the current supply requires.

`isReserveCompliant()` is a public view function that returns whether the reserve ratio holds - useful for monitoring and off-chain verification.
