Mitigation of M-04: Fully Alleviated
The sponsor implemented the recommended course of action to address this exhibit, evaluating whether the _maxCoupons value has been reached solely when a new coupon is introduced to the exchange. A snippet of the contract with the remediated code showcased can be found below:
/**
* @notice Sells a bond against KIBToken.
* @param tokenId Sold bond tokenId.
*/
function sellBond(uint256 tokenId) external override whenNotPaused whenNotDeprecated {
IKUMAAddressProvider KUMAAddressProvider = _KUMAAddressProvider;
IKUMABondToken KUMABondToken = IKUMABondToken(KUMAAddressProvider.getKUMABondToken());
IKUMABondToken.Bond memory bond = KUMABondToken.getBond(tokenId);
/**
* MITIGATION BLOCK OF M-04 START
*/
if (!_coupons.contains(bond.coupon) && _coupons.length() == _maxCoupons) {
revert Errors.MAX_COUPONS_REACHED();
}
/**
* MITIGATION BLOCK OF M-04 END
*/
if (bond.riskCategory != _riskCategory) {
revert Errors.WRONG_RISK_CATEGORY();
}
if (bond.maturity <= block.timestamp) {
revert Errors.CANNOT_SELL_MATURED_BOND();
}
IKIBToken KIBToken = IKIBToken(KUMAAddressProvider.getKIBToken(_riskCategory));
uint256 referenceRate = IMCAGRateFeed(KUMAAddressProvider.getRateFeed()).getRate(_riskCategory);
if (bond.coupon < referenceRate) {
revert Errors.COUPON_TOO_LOW();
}
if (_coupons.length() == 0) {
_minCoupon = bond.coupon;
_coupons.add(bond.coupon);
} else {
if (bond.coupon < _minCoupon) {
_minCoupon = bond.coupon;
}
if (!_coupons.contains(bond.coupon)) {
_coupons.add(bond.coupon);
}
}
_couponInventory[bond.coupon]++;
_bondReserve.add(tokenId);
uint256 bondValue = _getBondValue(bond.issuance, bond.term, bond.coupon, bond.principal);
_bondBaseValue[tokenId] = bondValue.wadToRay().rayDiv(KIBToken.getUpdatedCumulativeYield());
uint256 fee = _calculateFees(bondValue);
uint256 mintAmount = bondValue;
if (fee > 0) {
mintAmount = bondValue - fee;
KIBToken.mint(KUMAAddressProvider.getKUMAFeeCollector(_riskCategory), fee);
}
KIBToken.mint(msg.sender, mintAmount);
KUMABondToken.safeTransferFrom(msg.sender, address(this), tokenId);
emit FeeCharged(fee);
emit BondSold(tokenId, mintAmount, msg.sender);
}
As such, the contract will correctly permit the sale of a bond whose coupon is already in the _coupons list when the _maxCoupon value has been reached. An accompanying test was introduced to the codebase's KUMASwap.sellBond.t.sol file that ensures the sale of a bond whose coupon is in the list goes through regardless of whether _maxCoupons was reached.
Mitigation of M-04: Fully Alleviated
The sponsor implemented the recommended course of action to address this exhibit, evaluating whether the
_maxCouponsvalue has been reached solely when a new coupon is introduced to the exchange. A snippet of the contract with the remediated code showcased can be found below:As such, the contract will correctly permit the sale of a bond whose coupon is already in the
_couponslist when the_maxCouponvalue has been reached. An accompanying test was introduced to the codebase'sKUMASwap.sellBond.t.solfile that ensures the sale of a bond whose coupon is in the list goes through regardless of whether_maxCouponswas reached.