diff --git a/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansImpl.java b/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansImpl.java index 03b222f3a..731d9e806 100644 --- a/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansImpl.java +++ b/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansImpl.java @@ -464,6 +464,7 @@ private void _returnAsset(String _from, BigInteger _value, String _collateralSym public void redeemCollateral(Address _collateralAddress, BigInteger _amount) { checkStatus(); loansOn(); + Context.require(!getRedemptionExemption(_collateralAddress), "bnUSD cannot be redeemed for this collateral"); Address caller = Context.getCaller(); String collateralSymbol = CollateralDB.getSymbol(_collateralAddress); BigInteger daofundFee = redemptionDaoFee.getOrDefault(BigInteger.ZERO).multiply(_amount).divide(POINTS); @@ -888,6 +889,17 @@ public BigInteger getRedemptionFee() { return redemptionFee.get(); } + @External + public void setRedemptionExemption(Address token, boolean exempt) { + onlyGovernance(); + redemptionExemptions.set(token, exempt); + } + + @External(readonly = true) + public boolean getRedemptionExemption(Address token) { + return redemptionExemptions.getOrDefault(token, false); + } + @External public void setRedemptionDaoFee(BigInteger _fee) { onlyGovernance(); diff --git a/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansVariables.java b/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansVariables.java index 70271a9ed..c6ec50817 100644 --- a/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansVariables.java +++ b/core-contracts/Loans/src/main/java/network/balanced/score/core/loans/LoansVariables.java @@ -42,6 +42,7 @@ public class LoansVariables { private static final String REDEMPTION_DAO_FEE = "redemption_dao_fee"; private static final String RETIREMENT_BONUS = "retirement_bonus"; private static final String NEW_LOAN_MINIMUM = "new_loan_minimum"; + private static final String REDEMPTION_EXEMPTIONS = "redemption_exemptions"; private static final String REDEEM_BATCH_SIZE = "redeem_batch_size"; private static final String MAX_RETIRE_PERCENT = "max_retire_percent"; @@ -69,6 +70,7 @@ public class LoansVariables { static final VarDB newLoanMinimum = Context.newVarDB(NEW_LOAN_MINIMUM, BigInteger.class); static final VarDB redeemBatch = Context.newVarDB(REDEEM_BATCH_SIZE, Integer.class); static final VarDB maxRetirePercent = Context.newVarDB(MAX_RETIRE_PERCENT, BigInteger.class); + static final DictDB redemptionExemptions= Context.newDictDB(REDEMPTION_EXEMPTIONS, Boolean.class); static final VarDB
expectedToken = Context.newVarDB(EXPECTED_TOKEN, Address.class); static final VarDB amountReceived = Context.newVarDB(AMOUNT_RECEIVED, BigInteger.class); diff --git a/core-contracts/Loans/src/test/java/network/balanced/score/core/loans/LoansTest.java b/core-contracts/Loans/src/test/java/network/balanced/score/core/loans/LoansTest.java index 77d2fdd3e..238bc010c 100644 --- a/core-contracts/Loans/src/test/java/network/balanced/score/core/loans/LoansTest.java +++ b/core-contracts/Loans/src/test/java/network/balanced/score/core/loans/LoansTest.java @@ -1679,6 +1679,27 @@ void redeemCollateral_redeemAboveMax() { expectErrorMessage(redeemAboveMaxSize, expectedErrorMessage); } + @Test + void redeemCollateral_exemptCollateral() { + // Arrange + Account account1 = sm.createAccount(); + Account redeemer = sm.createAccount(); + BigInteger collateral = BigInteger.valueOf(4000).multiply(EXA); + BigInteger loan = BigInteger.valueOf(400).multiply(EXA); + + BigInteger sICXRate = EXA.divide(BigInteger.TWO); + mockOraclePrice("sICX", sICXRate); + + // Act && Assert + loans.invoke(governance.account, "setRedemptionExemption", sicx.getAddress(), true); + takeLoanICX(account1, "bnUSD", collateral, loan); + + String expectedErrorMessage = "bnUSD cannot be redeemed for this collateral"; + Executable redeemExemptToken = () -> loans.invoke(redeemer, "redeemCollateral", sicx.getAddress(), BigInteger.ONE); + expectErrorMessage(redeemExemptToken, expectedErrorMessage); + } + + @Test void redeemCollateral_iETH() { // Arrange diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Loans.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Loans.java index 873f99f6c..6e4af666d 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Loans.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Loans.java @@ -148,6 +148,12 @@ void depositAndBorrow(@Optional String _asset, @Optional BigInteger _amount, @Op @External(readonly = true) BigInteger getRedemptionDaoFee(); + @External + void setRedemptionExemption(Address token, boolean exempt); + + @External(readonly = true) + boolean getRedemptionExemption(Address token); + @External void setNewLoanMinimum(BigInteger _minimum); diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/Versions.java b/score-lib/src/main/java/network/balanced/score/lib/utils/Versions.java index d659c4b3f..bc08e7ced 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/utils/Versions.java +++ b/score-lib/src/main/java/network/balanced/score/lib/utils/Versions.java @@ -19,7 +19,7 @@ public class Versions { public final static String BALN = "v1.1.0"; public final static String DIVIDENDS = "v1.0.0"; - public final static String LOANS = "v1.2.0"; + public final static String LOANS = "v1.2.1"; public final static String RESERVE = "v1.0.0"; public final static String SICX = "v1.1.1"; public final static String STAKING = "v1.0.1";