Minting and Redeeming Senior Tranche Tokens (ERC-721)

Please refer to the SmartYield.sol repo for code references made on this page.


SMART Yield relies on minting and burning ERC-721 tokens to keep track of outstanding claims on the senior tranche's ABOND variable.
Upon minting, the user secures an ERC-721 token with a specific principal amount, gain amount, and maturity.
event BuySeniorBond(address indexed buyer, uint256 indexed seniorBondId, uint256 underlyingIn, uint256 gain, uint256 forDays);
Upon redemption, the user burns the ERC-721 token in exchange for the sum of the principal and the fixed yield, minus a fee.
event RedeemSeniorBond(address indexed owner, uint256 indexed seniorBondId, uint256 fee)

Minting Senior Tranche Bonds

To mint a senior tranche bond, the user must be able to secure a positive interest rate...
uint256 gain = bondGain(principalAmount_, forDays_);
gain >= minGain_,
"SY: buyBond minGain"
gain > 0,
"SY: buyBond gain 0"
gain < underlyingLoanable(),
"SY: buyBond underlyingLoanable"
... as well as select a maturity date within the approved range. (See: IController.sol)
Currently, senior tranche bonds must be minted with a maturity date between 1 and 365 days out from purchase. Future governance votes can seek to extend this range.
0 < forDays_ && forDays_ <= IController(controller).BOND_LIFE_MAX(),
"SY: buyBond forDays"
With these requirements met, the ERC-721 token can be minted with properties for principal amount, the fixed yield, and its maturity date. (See IProvider.sol)
address buyer = msg.sender;
IProvider(pool)._takeUnderlying(buyer, principalAmount_);
IProvider(pool)._depositProvider(principalAmount_, 0);
SeniorBond memory b =
uint256(1 days) * uint256(forDays_) + issuedAt,
_mintBond(buyer, b);
emit BuySeniorBond(buyer, seniorBondId, principalAmount_, gain, forDays_);
return gain;

Redeeming Senior Tranche Bonds

Senior tranche bonds can be redeemed by whomever holds the ERC-721 token upon maturity. (See: IBond.sol)
address payTo = IBond(seniorBond).ownerOf(bondId_)
Senior tranche bond holders are entitled to the sum of the principal and its fixed yield at either maturity or any time beyond.
Unredeemed senior tranche bonds continue to earn yield for the junior tranche.
uint256 payAmnt = seniorBonds[bondId_].gain.add(seniorBonds[bondId_].principal)
The ERC-721 token is burned upon redemption. (See: IBond.sol)
With the ERC-721 token burned, the associated principal and yield are withdrawn from the senior tranche and returned to the redeemer, sans the redemption fee. (See IProvider.sol)
IProvider(pool)._withdrawProvider(payAmnt, fee);
IProvider(pool)._sendUnderlying(payTo, payAmnt);
emit RedeemSeniorBond(payTo, bondId_, fee);

Senior Redemption Fees

Senior tranche bonds are charged a 5% fee on the fixed yield upon redemption.
uint256 fee = MathUtils.fractionOf(seniorBonds[bondId_].gain, IController(controller).FEE_REDEEM_SENIOR_BOND())
For example, a $10,000 senior tranche bond that earns a fixed rate of 10% would be worth $11,000 at maturity and cost $50 to redeem, leaving the user with $10,950.
payAmnt = payAmnt.sub(fee)
This fee is then directed to the address set as "feesOwner" in IController.sol. In practice, this is the DAO's treasury address.