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 purchasesupdateAdminFeeWallet()
: Update admin fee recipientupdateCanceledPurchaseWallet()
: Update cancellation refund recipientupdateOriginatorPaymentWallet()
: Update originator payment recipient
Automation Admin Functions
executePurchase()
: Execute a purchase transactioncancelPurchase()
: Cancel and refund a purchase
Error Handling
The contract provides comprehensive error messages for debugging:
PurchaseContract_PurchaseIdAlreadyUsed
: Duplicate purchase IDPurchaseContract_TokenRecipientAmlKycNotPassed
: Recipient compliance failurePurchaseContract_PayerAmlKycNotPassed
: Payer compliance failurePurchaseContract_InvalidTotalAmount
: Amount calculation mismatchPurchaseContract_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.