Developer Reference

This page documents the public interface of the DinoPrimary contract:

  • Solidity interface (high-level)

  • Function-by-function behavior (with access control & revert reasons)

  • Events & custom errors

Admin concepts (roles, issuerSafe, preminted, rules, etc.) are described on the Admin & Management page; here we focus on how to call the contract.

Contract & Imports

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC3643 } from "@erc3643org/erc-3643/contracts/ERC-3643/IERC3643.sol";
import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
import { IDinoPrimary } from "./interfaces/IDinoPrimary.sol";
import { IFeeCollector } from "./interfaces/IFeeCollector.sol";

contract DinoPrimary is IDinoPrimary { /* ... */ }

Each asset has its own instance of DinoPrimary, typically deployed and initialized via DinoFactory.

State Variables (Public Getters)

DinoPrimary exposes a few public variables:

IERC3643 public erc3643;
address  public issuerSafe;
bool     public preminted;
IFeeCollector public ecosystemFeeCollector;

uint256 public nonce;
mapping(address => PaymentToken) public approvedPaymentTokens;
  • erc3643() – underlying ERC-3643 token for this primary rail.

  • issuerSafe() – address receiving subscription proceeds and paying redemptions.

  • preminted() – true if supply is pre-minted in a treasury and transferred; false if DinoPrimary mints/burns.

  • ecosystemFeeCollector() – protocol fee collector.

  • nonce() – incremented per subscription / redemption; also emitted in events.

  • approvedPaymentTokens(token) – returns price feed and stability info for a payment token.

circle-info

You won’t write to these directly – use the admin functions and rely on DinoFactory for initialization.

Solidity Interface

Access control (roles) is enforced by AccessManaged via an AccessManagerarrow-up-right contract; see Admin & Management for role mapping.

Investor Functions

subscribe

Description

Subscribes amount of ERC-3643 tokens using paymentToken as consideration.

  • For preminted assets:

    • Transfers amount of ERC-3643 from issuerSafe to msg.sender.

  • For non-preminted assets:

    • Mints amount of ERC-3643 to msg.sender.

In both cases:

  • Calculates total cost using a price feed implementing the AggregatorV3Interfacearrow-up-right.

  • Transfers paymentToken from investor to issuerSafe.

  • Collects protocol fee via ecosystemFeeCollector.

  • Emits Subscribed(nonce, investor, paymentToken, amount, totalCost).

Reverts if:

  • Subscriptions are closed (SubscriptionClosed).

  • amount < minAmount or amount > maxAmount (AmountBelowMinimum / AmountAboveMaximum).

  • paymentToken is not approved (PaymentTokenNotApproved).

  • ERC-3643 transfer / mint is not compliant (TransferNotCompliant, InvestorNotQualified).

  • Price feed issues (InvalidPriceFeed).

  • Fee collection fails (e.g. missing approval / balance on fee token).

redeem

Description

Redeems amount of ERC-3643 tokens back to the issuer, and pays the investor in paymentToken.

  • For preminted assets:

    • Transfers ERC-3643 from msg.sender back to issuerSafe.

  • For non-preminted assets:

    • Burns ERC-3643 from msg.sender (DinoPrimary is an authorized agent).

Then:

  • Computes payment amount based on NAV / price feed.

  • Applies redemption malus (haircut) if configured.

  • Transfers paymentToken from issuerSafe to investor.

  • Collects protocol fee.

  • Emits Redeemed(nonce, investor, paymentToken, amount, paymentAmount).

Reverts if:

  • Redemptions are closed (RedemptionClosed).

  • amount < minAmount or amount > maxAmount (AmountBelowMinimum / AmountAboveMaximum).

  • paymentToken not approved.

  • Investor or transfer not compliant.

  • Price feed invalid.

  • issuerSafe doesn’t have enough paymentToken balance / allowance.

  • Fee collection fails (e.g. missing approval / balance on fee token).

Preview Functions (Read-Only Quotes)

These functions do not modify state and allow UIs or off-chain systems to quote amounts without executing the operation.

previewSubscribeWithExactErc3643

Returns how much paymentToken is required to subscribe erc3643Amount of the asset.

previewSubscribeWithExactToken

Returns how many ERC-3643 tokens the investor would receive when paying paymentTokenAmount.

previewRedeemWithExactErc3643

Returns net payment after applying redemption malus for redeeming erc3643Amount.

previewRedeemWithExactToken

Returns how many ERC-3643 tokens the investor needs to redeem to receive paymentTokenAmount after malus.

circle-check

Payment Token Management

circle-exclamation

addPaymentToken

Registers a new payment token:

  • token – ERC-20 used for payments.

  • priceFeed – AggregatorV3Interfacearrow-up-right for token vs pricing currency.

  • isStable – true if the token is considered stable (e.g. fully backed stablecoin).

Reverts if:

  • token is zero address (ZeroAddress).

  • Token already added (PaymentTokenAlreadyAdded).

removePaymentToken

Removes a payment token. It will no longer be accepted for new subscriptions or redemptions.

Reverts if:

  • Token is not in the approved set (PaymentTokenNotApproved).

updatePaymentToken

Updates price feed and stability flag for an existing payment token.

Reverts if token is not approved.

getPaymentTokens / getPaymentTokenCount

Allow enumerating all approved payment tokens, on top of the approvedPaymentTokens(token) getter.

Rules Management

circle-exclamation

updateSubscriptionRules

Sets subscription period and per-tx min/max.

  • dateOpened – unix timestamp when subscriptions start.

  • dateClosed – unix timestamp when subscriptions end (0 = no end).

  • minAmount / maxAmount – per-call bounds for amount.

Reverts if minAmount > maxAmount (InvalidAmounts).

updateRedemptionRules

Same as subscription rules, plus:

  • redemptionMalus – in basis points (e.g. 100 = 1%, 500 = 5%) applied as haircut on redemptions.

subscriptionRules

Returns current subscription rule set and whether the window is open at block.timestamp.

redemptionRules

Same for redemptions, including the currently configured malus.

Admin Functions

circle-exclamation

updateIssuerSafe

Updates the address that:

  • Receives subscription proceeds.

  • Pays redemptions.

Reverts if newIssuerSafe is zero address.

updatePreminted

Toggles mode:

  • true – transfer from issuerSafe (treasury).

  • false – mint/burn via ERC-3643 permissions.

Emits PremintedUpdated.

Events

  • event IssuerSafeUpdated(address indexed oldIssuerSafe, address indexed newIssuerSafe)

  • event PremintedUpdated(address indexed updatedBy, bool preminted)

  • event PaymentTokenAdded(address indexed token, address priceFeed, bool isStable)

  • event PaymentTokenRemoved(address indexed token)

  • event PaymentTokenUpdated(address indexed token, address priceFeed, bool isStable)

  • event SubscriptionRulesUpdated(uint256 dateOpened, uint256 dateClosed, uint256 minAmount, uint256 maxAmount, address indexed updatedBy)

  • event RedemptionRulesUpdated(uint256 dateOpened, uint256 dateClosed, uint256 minAmount, uint256 maxAmount, uint16 redemptionMalus, address indexed updatedBy)

  • event Subscribed(uint256 indexed nonce, address indexed investor, address indexed paymentToken, uint256 amount, uint256 totalCost)

  • event Redeemed(uint256 indexed nonce, address indexed investor, address indexed paymentToken, uint256 amount, uint256 paymentAmount)

Plus inherited:

  • AuthorityUpdated(address authority) from AccessManaged.

Custom Errors (from ErrorsLib)

DinoPrimary relies on a shared error library. Relevant errors include:

  • ZeroAddress() – one of the addresses is zero.

  • SubscriptionClosed() – subscription window not open.

  • RedemptionClosed() – redemption window not open.

  • AmountBelowMinimum(uint256 amount, uint256 min)

  • AmountAboveMaximum(uint256 amount, uint256 max)

  • PaymentTokenAlreadyAdded(address token)

  • PaymentTokenNotApproved(address token)

  • InvalidAmounts() – minAmount > maxAmount in rules updates.

  • InvalidPriceFeed() – price feed returns non-positive value.

  • InvestorNotQualified(address investor) – identity / eligibility issue.

  • TransferNotCompliant() – ERC-3643 compliance prevents transfer/mint/burn.

These are meant to be developer-friendly and easily mapped to front-end error messages.

Last updated