Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix QA #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/kuma-protocol/KIBToken.sol
Expand Up @@ -22,7 +22,6 @@ contract KIBToken is IKIBToken, ERC20PermitUpgradeable, UUPSUpgradeable {
using Roles for bytes32;
using WadRayMath for uint256;

uint256 public constant MAX_YIELD = 1e29;
uint256 public constant MAX_EPOCH_LENGTH = 365 days;
uint256 public constant MIN_YIELD = WadRayMath.RAY;

Expand Down Expand Up @@ -68,6 +67,9 @@ contract KIBToken is IKIBToken, ERC20PermitUpgradeable, UUPSUpgradeable {
if (epochLength == 0) {
revert Errors.EPOCH_LENGTH_CANNOT_BE_ZERO();
}
if (epochLength > MAX_EPOCH_LENGTH) {
revert Errors.NEW_EPOCH_LENGTH_TOO_HIGH();
}
if (address(KUMAAddressProvider) == address(0)) {
revert Errors.CANNOT_SET_TO_ADDRESS_ZERO();
}
Expand Down Expand Up @@ -104,7 +106,7 @@ contract KIBToken is IKIBToken, ERC20PermitUpgradeable, UUPSUpgradeable {
if (epochLength > MAX_EPOCH_LENGTH) {
revert Errors.NEW_EPOCH_LENGTH_TOO_HIGH();
}
if (epochLength > _epochLength) {
if (_getPreviousEpochTimestamp() >= (block.timestamp / epochLength * epochLength)) {
_refreshCumulativeYield();
_refreshYield();
}
Expand Down
2 changes: 1 addition & 1 deletion src/kuma-protocol/KUMAFeeCollector.sol
Expand Up @@ -220,7 +220,7 @@ contract KUMAFeeCollector is IKUMAFeeCollector, UUPSUpgradeable, Initializable {
IERC20 KIBToken = IERC20(_KUMAAddressProvider.getKIBToken(_riskCategory));
uint256 availableIncome = KIBToken.balanceOf(address(this));

if (availableIncome > 0) {
if (availableIncome > 0 && _payees.length() > 0) {
_release(KIBToken, availableIncome);
}
}
Expand Down
22 changes: 10 additions & 12 deletions src/kuma-protocol/KUMASwap.sol
Expand Up @@ -205,25 +205,23 @@ contract KUMASwap is IKUMASwap, PausableUpgradeable, UUPSUpgradeable {
uint256 bondFaceValue = _getBondValue(bond.issuance, bond.term, bond.coupon, bond.principal);
uint256 realizedBondValue = _bondBaseValue[tokenId].rayMul(KIBToken.getUpdatedCumulativeYield()).rayToWad();

bool requireClone = bondFaceValue > realizedBondValue;

if (requireClone) {
if (bondFaceValue > realizedBondValue) {
uint256 previousEpochTimestamp = KIBToken.getPreviousEpochTimestamp();
uint256 yield = KIBToken.getYield();
_updateMinCoupon();
KIBToken.burn(msg.sender, realizedBondValue);
_cloneBonds[tokenId] = IKBCToken(KUMAAddressProvider.getKBCToken()).issueBond(
msg.sender,
IKBCToken.CloneBond({
parentId: tokenId,
issuance: KIBToken.getPreviousEpochTimestamp(),
coupon: KIBToken.getYield(),
issuance: previousEpochTimestamp,
coupon: yield,
principal: realizedBondValue
})
);
}

_updateMinCoupon();

KIBToken.burn(msg.sender, realizedBondValue);

if (!requireClone) {
} else {
_updateMinCoupon();
KIBToken.burn(msg.sender, realizedBondValue);
KUMABondToken.safeTransferFrom(address(this), msg.sender, tokenId);
}

Expand Down
6 changes: 6 additions & 0 deletions src/mcag-contracts/Blacklist.sol
Expand Up @@ -35,6 +35,9 @@ contract Blacklist is IBlacklist {
* @param account The address to blacklist
*/
function blacklist(address account) external override onlyBlacklister {
if (_blacklisted[account]) {
revert Errors.BLACKLIST_ACCOUNT_IS_BLACKLISTED(account);
}
_blacklisted[account] = true;
emit Blacklisted(account);
}
Expand All @@ -44,6 +47,9 @@ contract Blacklist is IBlacklist {
* @param account The address to remove from the blacklist
*/
function unBlacklist(address account) external override onlyBlacklister {
if (!_blacklisted[account]) {
revert Errors.BLACKLIST_ACCOUNT_IS_NOT_BLACKLISTED(account);
}
_blacklisted[account] = false;
emit UnBlacklisted(account);
}
Expand Down
3 changes: 3 additions & 0 deletions src/mcag-contracts/KYCToken.sol
Expand Up @@ -47,6 +47,9 @@ contract KYCToken is ERC721, IKYCToken {
* @param kycData KYCData struct storing metadata.
*/
function mint(address to, KYCData calldata kycData) external override onlyRole(Roles.MCAG_MINT_ROLE) {
if (to != kycData.owner) {
revert Errors.KYC_DATA_OWNER_MISMATCH(to, kycData.owner);
}
_tokenIdCounter.increment();
uint256 tokenId = _tokenIdCounter.current();
_kycData[tokenId] = kycData;
Expand Down
4 changes: 3 additions & 1 deletion src/mcag-contracts/libraries/Errors.sol
Expand Up @@ -10,7 +10,9 @@ library Errors {
error ERC721_CALLER_IS_NOT_TOKEN_OWNER();
error ACCESS_CONTROL_ACCOUNT_IS_MISSING_ROLE(address account, bytes32 role);
error BLACKLIST_CALLER_IS_NOT_BLACKLISTER();
error BLACKLIST_ACCOUNT_IS_NOT_BLACKLISTED(address account);
error BLACKLIST_ACCOUNT_IS_BLACKLISTED(address account);
error TRANSMITTED_ANSWER_TOO_HIGH(int256 answer, int256 maxAnswer);
error TOKEN_IS_NOT_TRANSFERABLE();
}
error KYC_DATA_OWNER_MISMATCH(address to, address owner);
}
10 changes: 10 additions & 0 deletions test/kuma-protocol/KUMAFeeCollector.t.sol
Expand Up @@ -105,6 +105,16 @@ contract KUMAFeeCollectorTest is BaseSetUp {
}
}

function test_release_WithNoPayees() external {
for (uint256 i; i < 4; i++) {
_KUMAFeeCollector.removePayee(_payees[i]);
}
_KIBToken.mint(address(_KUMAFeeCollector), 4 ether);
vm.expectEmit(false, false, false, true);
_KUMAFeeCollector.addPayee(_payees[0], 100); // if this line emitts anything other than a PayeeAdded event, test will fail
emit PayeeAdded(_payees[0], 100); // Technically the actual event passed into the vm.expectEmit call, since the expected event was emitted in the line above
}

function test_release_RevertWhen_NoAvailableIncome() public {
vm.expectRevert(Errors.NO_AVAILABLE_INCOME.selector);
_KUMAFeeCollector.release();
Expand Down
24 changes: 24 additions & 0 deletions test/kuma-protocol/kib-token/KIBToken.setEpoch.t.sol
Expand Up @@ -50,6 +50,30 @@ contract KIBTokenSetEpoch is KIBTokenSetUp {
assertEq(_KIBToken.balanceOf(_alice), _YIELD.rayPow(4 hours).rayMul(10 ether));
}

function test_setEpochLength_ToLowerEpochAndShiftBackOfPreviousEpochTimestamp() public {
_KIBToken.mint(_alice, 10 ether);
skip(4 hours);
uint256 aliceBalanceBefore = _KIBToken.balanceOf(_alice);

// Timestamp is now 30 years + 8 hours aligning with 4 hours epochs
// Set new epoch where block.timestamp % new epoch length is less than block.timestamp % old epoch length
uint256 previousEpochTimestampBefore = _KIBToken.getPreviousEpochTimestamp();
_KIBToken.setEpochLength(3 hours);
uint256 previousEpochTimestampAfter = _KIBToken.getPreviousEpochTimestamp();
uint256 aliceBalanceAfter = _KIBToken.balanceOf(_alice);

// Previous epoch timestamp should now be shifted back 2 hours per the formula
assertEq(previousEpochTimestampBefore - previousEpochTimestampAfter, 2 hours);
assertEq(block.timestamp - previousEpochTimestampAfter, 2 hours);
// Alice balance should remane the same
assertEq(aliceBalanceBefore, aliceBalanceAfter);

// Skip 1 hours to the end of the new epoch
skip(1 hours);
// Alice should now have accrued 5 hours of interests in total
assertEq(_KIBToken.balanceOf(_alice), _YIELD.rayPow(5 hours).rayMul(10 ether));
}

function test_setEpochLength_RevertWhen_SetToZero() public {
vm.expectRevert(Errors.EPOCH_LENGTH_CANNOT_BE_ZERO.selector);
_KIBToken.setEpochLength(0);
Expand Down
15 changes: 15 additions & 0 deletions test/kuma-protocol/kib-token/KIBToken.setters.t.sol
Expand Up @@ -55,6 +55,21 @@ contract KIBTokenSetters is KIBTokenSetUp {
)
);

vm.expectRevert(Errors.NEW_EPOCH_LENGTH_TOO_HIGH.selector);
_deployUUPSProxy(
address(newKIBToken),
abi.encodeWithSelector(
IKIBToken.initialize.selector,
_NAME,
_SYMBOL,
365 days + 1,
_KUMAAddressProvider,
_CURRENCY,
_COUNTRY,
_TERM
)
);

vm.expectRevert(Errors.CANNOT_SET_TO_ADDRESS_ZERO.selector);
_deployUUPSProxy(
address(newKIBToken),
Expand Down
11 changes: 11 additions & 0 deletions test/mcag-contracts/Blacklist.t.sol
Expand Up @@ -50,6 +50,12 @@ contract BlacklistTest is Test {
_blacklist.blacklist(address(this));
}

function test_blackilst_RevertWhen_AccountIsAlreadyBlacklisted() public {
_blacklist.blacklist(_alice);
vm.expectRevert(abi.encodeWithSelector(Errors.BLACKLIST_ACCOUNT_IS_BLACKLISTED.selector, _alice));
_blacklist.blacklist(_alice);
}

function test_unBlacklist() public {
_blacklist.blacklist(_alice);
vm.expectEmit(true, false, false, true);
Expand All @@ -64,4 +70,9 @@ contract BlacklistTest is Test {
vm.prank(_alice);
_blacklist.unBlacklist(address(this));
}

function test_unBlacklist_RevertWhen_AccountIsNotBlacklisted() public {
vm.expectRevert(abi.encodeWithSelector(Errors.BLACKLIST_ACCOUNT_IS_NOT_BLACKLISTED.selector, _alice));
_blacklist.unBlacklist(_alice);
}
}
5 changes: 5 additions & 0 deletions test/mcag-contracts/KYCToken.t.sol
Expand Up @@ -72,6 +72,11 @@ contract KYCTokenTest is Test {
_kycToken.mint(_alice, _kycData);
}

function test_mint_RevertWhen_KycDataOwnerIsNotTheSameAsToAddress() public {
vm.expectRevert(abi.encodeWithSelector(Errors.KYC_DATA_OWNER_MISMATCH.selector, _alice, address(this)));
_kycToken.mint(_alice, _kycData);
}

function test_burn() public {
_kycToken.mint(address(this), _kycData);
vm.expectEmit(false, false, false, true);
Expand Down