DTA Fund and Distributor Management
This page covers the operator-side flows of DTA v2: onboarding fund admins, registering fund tokens, managing distributors, and wiring cross-DTA settlement. Investor-facing flows (subscriptions, redemptions) live in Subscriptions and Redemptions.
All examples assume an extension constructed as in DTA Overview:
ext, _ := dtaop.New(&dtaop.Options{
AccountAddress: smartAccount.Hex(),
DTARequestManagementAddress: mgmtAddr.Hex(),
DTARequestSettlementAddress: settleAddr.Hex(),
})
Fund admin onboarding
Register once per Smart Account that will act as a Fund Administrator:
op, err := ext.PrepareRegisterFundAdminOperation()
Underlying call: DTARequestManagement.registerFundAdmin(). Emits FundAdminRegistered:
type FundAdminRegistered struct {
FundAdminAddr common.Address
}
Register a fund token
Each tokenised fund is registered once with its complete configuration:
import dtaevents "github.com/smartcontractkit/crec-sdk-ext-dta/v2/events"
tokenData := dtaevents.FundTokenData{
FundTokenAddr: fundTokenAddr,
NavFeedDecimals: 8,
PurchaseTokenRoundingDecimals: 6,
PurchaseTokenDecimals: 6, // e.g. USDC
FundRoundingDecimals: 18,
FundTokenDecimals: 18,
RequestsPerDay: 4,
NavAddr: navOracleAddr,
TokenChainSelector: 5009297550715157269, // Ethereum mainnet
DtaRequestSettlementAddr: settleAddr,
TimezoneOffsetSecs: big.NewInt(0),
NavTTL: big.NewInt(86400),
PaymentInfo: dtaevents.DTAPayment{
OffChainPaymentCurrency: 0,
PaymentTokenSourceAddr: paymentTokenAddr,
PaymentTokenDestAddr: paymentDestAddr,
},
}
op, err := ext.PrepareRegisterFundTokenOperation(fundTokenId, tokenData)
Underlying call: DTARequestManagement.registerFundToken(fundTokenId, tokenData). Emits FundTokenRegistered:
type FundTokenRegistered struct {
FundAdminAddr common.Address
FundTokenId common.Hash
FundTokenAddr common.Address
NavAddr common.Address
TokenChainSelector uint64
}
fundTokenId is the Fund Token ID, a [32]byte (bytes32) identifier defined by the DTA Technical Standard. Choose a derivation strategy that fits your fund-token registry; see the DTA Standard glossary for the canonical definition.
Toggle availability
A fund token can be temporarily disabled (rejecting new requests) without re-registering:
op, _ := ext.PrepareDisableFundTokenOperation(fundTokenId)
op, _ := ext.PrepareEnableFundTokenOperation(fundTokenId)
Underlying calls: disableFundToken(fundTokenId) / enableFundToken(fundTokenId). Both emit no separate event; observe via the on-chain reference data.
Distributor lifecycle
A Fund Distributor is a Smart Account authorised to submit subscription / redemption requests on behalf of investors.
Register a distributor
op, err := ext.PrepareRegisterDistributorOperation(distributorWalletAddr)
Underlying call: DTARequestManagement.registerDistributor(distributorWalletAddr). Emits DistributorRegistered:
type DistributorRegistered struct {
DistributorAddr common.Address
}
Authorise / revoke a distributor for a fund token (v2 model)
DTA v2 uses an authorise / revoke model rather than the v1 allow / disallow flag. The fund admin signs authorize or revoke calls to set per-token distributor permissions:
op, _ := ext.PrepareAuthorizeDistributorForTokenOperation(fundAdminAddr, fundTokenId, distributorAddr)
op, _ := ext.PrepareRevokeDistributorForTokenOperation(fundAdminAddr, fundTokenId, distributorAddr)
Underlying calls:
authorizeDistributorForToken(fundAdminAddr, fundTokenId, distributorAddr)revokeDistributorForToken(fundAdminAddr, fundTokenId, distributorAddr)
Both emit DistributorAuthorizationUpdated:
type DistributorAuthorizationUpdated struct {
DistributorAddr common.Address
FundAdminAddr common.Address
FundTokenId common.Hash
Authorized bool
}
Allow-list (per-token, no admin involvement)
For lower-trust scenarios where the fund admin already pre-approved a category of distributors, the per-token allow-list is the lightweight knob:
op, _ := ext.PrepareAllowDistributorForTokenOperation(fundTokenId, distributorAddr)
op, _ := ext.PrepareDisallowDistributorForTokenOperation(fundTokenId, distributorAddr)
Emits FundTokenAllowlistUpdated:
type FundTokenAllowlistUpdated struct {
FundAdminAddr common.Address
FundTokenId common.Hash
DistributorAddr common.Address
Allowed bool
}
Cross-DTA settlement
For cross-chain settlement topologies, configure which remote DTA contracts are allowed to settle against your settlement contract. The Chain Selector identifies the remote chain.
op, _ := ext.PrepareAllowDTAOperation(
dtaAddr, // remote DTA contract
dtaChainSelector, // CCIP chain selector
fundAdminAddr,
fundTokenId,
fundTokenAddr,
dtaevents.TokenMintTypeMint, // or TokenMintTypeIssueTokens
dtaevents.TokenBurnTypeBurn, // or BurnFrom / BurnWithReason / ForceBurn
)
op, _ := ext.PrepareDisallowDTAOperation(dtaAddr, dtaChainSelector, fundAdminAddr, fundTokenId)
Emits DTAAdded / DTARemoved:
type DTAAdded struct {
DtaAddr common.Address
DtaChainSelector uint64
FundAdminAddr common.Address
FundTokenId common.Hash
FundTokenAddr common.Address
}
type DTARemoved struct {
DtaAddr common.Address
DtaChainSelector uint64
FundAdminAddr common.Address
FundTokenId common.Hash
}
Match the TokenMintType / TokenBurnType to the fund token contract's interface; see the v2 events types.go for the full mapping.
Settlement contract operations
Two ownership operations bind to the settlement contract:
op, _ := ext.PrepareTransferDTARequestSettlementOwnershipOperation(newOwner)
op, _ := ext.PrepareRenounceDTARequestSettlementOwnershipOperation()
These are standard OpenZeppelin Ownable operations.
Token withdrawals
Both contracts expose a withdrawTokens operation for sweeping accidentally-sent ERC-20 balances:
op, _ := ext.PrepareWithdrawManagementTokensOperation(token, recipient, amount)
op, _ := ext.PrepareWithdrawSettlementTokensOperation(token, recipient, amount)
Emits TokenWithdrawn:
type TokenWithdrawn struct {
Token common.Address
Recipient common.Address
Amount *big.Int
}
CCIP gas-limit tuning
For cross-chain operations, both contracts let the owner adjust the CCIP message gas limit:
op, _ := ext.PrepareSetManagementCCIPGasLimitOperation(big.NewInt(500_000))
op, _ := ext.PrepareSetSettlementCCIPGasLimitOperation(big.NewInt(500_000))
Tune in response to gas-limit-exceeded settlement failures.
Suggested onboarding sequence
1. PrepareRegisterFundAdminOperation (fund admin)
2. PrepareRegisterFundTokenOperation (fund admin, per token)
3. PrepareEnableFundTokenOperation (fund admin)
4. PrepareRegisterDistributorOperation (distributor)
5. PrepareAuthorizeDistributorForTokenOperation (fund admin, per (token, distributor))
6. (optionally) PrepareAllowDTAOperation (cross-chain DTA)
7. Investors can now subscribe / redeem
Next steps
- Subscriptions and Redemptions: investor-facing flows.
- DTA Events: every emitted event with its decoded struct.