VimenDocs
Reference

BasketToken API

The complete external interface of the basket contract.

One BasketToken instance per basket. ERC-20 (OpenZeppelin v5 base, 18 decimals) plus the interface below. Solidity 0.8.24, no proxy, no upgradeability, nonReentrant on state-changing entry points. Source is verified on Blockscout for every deployment (addresses).

Constructor

constructor(
    string  name_,
    string  symbol_,
    address[] tokens_,          // 2–20 constituents, no zero/duplicate, must be contracts
    uint256[] unitsPerBasket_,  // raw constituent wei per 1e18 basket wei, all > 0
    uint16  mintFeeBps_,        // ≤ MAX_FEE_BPS (50)
    address feeRecipient_,      // non-zero
    address guardian_,          // non-zero, immutable
    uint256 maxSupplyCap_,      // > 0, immutable ceiling
    uint256 initialSupplyCap_   // 0 < x ≤ maxSupplyCap
)

Each validation failure reverts with its own custom error (see Errors).

Core functions

mint

function mint(uint256 basketAmount, address to) external nonReentrant

Mints basketAmount (gross) by pulling ceil(basketAmount × units[i] / 1e18) of every constituent via safeTransferFrom; the caller must have approved each constituent. The contract verifies actual balance deltas (delta ≥ required) to reject non-standard transfer behavior. to receives basketAmount − fee; the fee (basketAmount × mintFeeBps / 10_000) is minted to feeRecipient. Reverts with MintingPaused, SupplyCapExceeded, or InsufficientDeposit(token). Emits Minted.

redeem

function redeem(uint256 basketAmount, address to) external nonReentrant

Burns basketAmount from the caller and transfers floor(basketAmount × units[i] / 1e18) of each constituent to to. No pause, cap or guardian power gates this function; the only possible external failure is a constituent token itself reverting transfers. No fee. Emits Redeemed.

Guardian functions

Callable only by the immutable guardian (reverts NotGuardian otherwise). This is the complete privileged surface:

function setMintPaused(bool paused) external onlyGuardian      // minting only
function setSupplyCap(uint256 newCap) external onlyGuardian    // ≤ maxSupplyCap
function setFeeRecipient(address newRecipient) external onlyGuardian

Views

function constituents() external view returns (address[] memory)
function units() external view returns (uint256[] memory)   // raw wei per 1e18 basket wei

getRequiredUnits

function getRequiredUnits(uint256 basketAmount)
    external view returns (address[] memory tokens, uint256[] memory amounts)

Exact deposit per constituent for a mint: amounts[i] = ceil(basketAmount × units[i] / 1e18). It rounds up (protocol-favoring). mint pulls exactly these amounts, so approvals set from this view return to zero.

backingOf

function backingOf(uint256 basketAmount)
    external view returns (address[] memory tokens, uint256[] memory amounts)

The floor variant: what a redemption of basketAmount pays out.

isFullyBacked

function isFullyBacked() external view returns (bool)

Checks balanceOf(vault) ≥ totalSupply × units[i] / 1e18 for every constituent. Should always return true; it exists so anyone can monitor the invariant live on Blockscout.

Public state

MemberTypeNotes
guardianaddress immutableThe Safe; see Guardian
mintFeeBpsuint16 immutableFixed at deploy, ≤ 50
maxSupplyCapuint256 immutableCeiling the cap can never exceed
feeRecipientaddressGuardian-settable
supplyCapuint256Guardian-settable, ≤ maxSupplyCap
mintPausedboolGuardian-settable, never affects redeem
MAX_FEE_BPSuint256 constant50
MIN_CONSTITUENTS / MAX_CONSTITUENTSuint256 constant2 / 20

Events

event Minted(address indexed sender, address indexed to, uint256 basketAmount, uint256 fee);
event Redeemed(address indexed sender, address indexed to, uint256 basketAmount);
event MintPausedSet(bool paused);
event SupplyCapSet(uint256 newCap);
event FeeRecipientSet(address indexed newRecipient);

Minted/Redeemed are the events to index for TVL, volume and fee-revenue analytics.

Errors

ErrorThrown when
LengthMismatchtokens.length != units.length at construction
InvalidConstituentCountFewer than 2 or more than 20 constituents
DuplicateTokenSame constituent twice
ZeroAddressZero token, fee recipient or guardian
NotAContract(token)Constituent address has no code
ZeroUnitsA unit of 0
FeeTooHighmintFeeBps > 50
ZeroSupplyCapZero max or initial cap
CapExceedsMaxInitial or new cap above maxSupplyCap
ZeroAmountMint/redeem of 0
MintingPausedMint while paused
SupplyCapExceededMint above supplyCap
InsufficientDeposit(token)Balance delta below required (e.g. fee-on-transfer token)
NotGuardianGuardian function from another address

On this page