In-kind issue and redeem
In-kind means the share and the basket move together. You never buy a share from the vault with a stablecoin at a printed price. That path lets someone move the print, mint cheap, and walk out with the inventory.
function create(uint256 shares) external nonReentrant {
Component[] memory c = components();
for (uint i; i < c.length; ++i) {
uint256 need = c[i].unitsPerShare * shares / 1e18;
require(IERC20(c[i].token).transferFrom(msg.sender, address(this), need), "in");
}
_mint(msg.sender, shares);
}
function redeem(uint256 shares) external nonReentrant {
Component[] memory c = components();
_burn(msg.sender, shares);
for (uint i; i < c.length; ++i) {
uint256 out = c[i].unitsPerShare * shares / 1e18;
require(IERC20(c[i].token).transfer(msg.sender, out), "out");
}
}Burn happens before payouts. Create pulls tokens before mint. That order is the difference between a vault and a bug.
How the share stays near NAV
If the share trades at $1.02 and the basket is worth $1.00, mint and sell. If it trades at $0.98, buy and redeem. The arb is mechanical. It dies the moment mint can be paid in cash at a cooked quote.