Skip to main content

Purchase Contract

The Purchase Contract (PurchaseContract.sol) provides a secure and automated system for handling token purchases with USDC payments. It integrates directly with the RestrictedLockupToken and InterestPayment contracts to provide atomic purchase transactions that include originator payments, admin fees, interest prefunding, and token minting.

Key Features

  • Atomic Purchase Transactions: All operations (payments, fees, minting) occur in a single transaction
  • Multi-Party Payment Distribution: Supports originator payments, admin fees, and interest prefunding
  • AML/KYC Integration: Validates both payer and recipient compliance status
  • Purchase ID Tracking: Prevents duplicate transactions with unique purchase identifiers
  • Automation-Ready: Designed for automated execution by external systems
  • Flexible Configuration: Configurable wallet addresses for different payment recipients

Architecture Overview

Purchase Execution Flow

1. Purchase Parameters

Each purchase requires a structured set of parameters:

struct PurchaseParams {
string purchaseId; // Unique identifier
address payerAddress; // Who pays USDC
address tokenRecipientAddress; // Who receives tokens
uint256 originatorPurchaseAmount; // Payment to originator
uint256 prefundedInterestAmount; // Interest prefunding
uint256 adminFeeExcludingPrefundedInterestAmount; // Admin fees
uint256 totalAmount; // Total USDC required
}

2. Execution Process

3. Token Calculation

The contract automatically calculates how many tokens to mint based on the originator purchase amount:

uint256 mintAmount = params.originatorPurchaseAmount / interestPayment.principalAmountPerToken();

Example:

  • Originator purchase amount: $50,000 USDC (50,000,000,000 with 6 decimals)
  • Principal amount per token: $1 (1,000,000 with 6 decimals)
  • Tokens minted: 50,000 tokens

Configuration Management

Wallet Address Management

The contract supports configurable wallet addresses for different payment types:

// Set originator payment wallet
purchaseContract.updateOriginatorPaymentWallet(newOriginatorWallet);

// Set admin fee wallet
purchaseContract.updateAdminFeeWallet(newAdminFeeWallet);

// Set canceled purchase wallet
purchaseContract.updateCanceledPurchaseWallet(newCanceledPurchaseWallet);

// Set automation admin (who can execute purchases)
purchaseContract.updateAutomationAdmin(newAutomationAdmin);

Purchase Cancellation

In case of issues, purchases can be canceled by the automation admin:

Validation and Security Features

AML/KYC Validation

Both payer and token recipient must pass AML/KYC validation:

// Validated automatically during purchase execution
require(tokenContract.isAmlKycPassed(params.tokenRecipientAddress), "Recipient AML/KYC failed");
require(tokenContract.isAmlKycPassed(params.payerAddress), "Payer AML/KYC failed");

Purchase ID Uniqueness

Each purchase must have a unique identifier to prevent duplicate executions:

require(!usedPurchaseIds[params.purchaseId], "Purchase ID already used");
usedPurchaseIds[params.purchaseId] = true;

Amount Validation

The contract validates that the total amount equals the sum of all components:

require(
params.totalAmount ==
params.originatorPurchaseAmount +
params.prefundedInterestAmount +
params.adminFeeExcludingPrefundedInterestAmount,
"Invalid total amount"
);

Integration Example

Here's a complete example of executing a purchase:

// 1. Prepare purchase parameters
PurchaseParams memory params = PurchaseParams({
purchaseId: "PURCHASE-2024-001",
payerAddress: investor,
tokenRecipientAddress: investor,
originatorPurchaseAmount: 100000e6, // $100,000 USDC
prefundedInterestAmount: 5000e6, // $5,000 USDC interest prefunding
adminFeeExcludingPrefundedInterestAmount: 500e6, // $500 USDC admin fee
totalAmount: 105500e6 // $105,500 USDC total
});

// 2. Investor approves USDC spending
usdcToken.approve(purchaseContractAddress, params.totalAmount);

// 3. Automation admin executes purchase
purchaseContract.executePurchase(params);

// Result:
// - Originator receives: $100,000 USDC
// - Interest payment contract receives: $5,000 USDC
// - Admin wallet receives: $500 USDC
// - Investor receives: 100,000 security tokens

Administrative Functions

Owner Functions

  • updateAutomationAdmin(): Change who can execute purchases
  • updateAdminFeeWallet(): Update admin fee recipient
  • updateCanceledPurchaseWallet(): Update cancellation refund recipient
  • updateOriginatorPaymentWallet(): Update originator payment recipient

Automation Admin Functions

  • executePurchase(): Execute a purchase transaction
  • cancelPurchase(): Cancel and refund a purchase

Error Handling

The contract provides comprehensive error messages for debugging:

  • PurchaseContract_PurchaseIdAlreadyUsed: Duplicate purchase ID
  • PurchaseContract_TokenRecipientAmlKycNotPassed: Recipient compliance failure
  • PurchaseContract_PayerAmlKycNotPassed: Payer compliance failure
  • PurchaseContract_InvalidTotalAmount: Amount calculation mismatch
  • PurchaseContract_AdminFeeWalletNotSet: Required wallet address not configured

This Purchase Contract design ensures secure, atomic token purchases while maintaining flexibility for different business models and payment structures.