diff --git a/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/AddressBranchDictDB.java b/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/AddressBranchDictDB.java
new file mode 100644
index 000000000..2898156d1
--- /dev/null
+++ b/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/AddressBranchDictDB.java
@@ -0,0 +1,50 @@
+package network.balanced.score.core.stakedlp;
+
+import foundation.icon.xcall.NetworkAddress;
+import score.Address;
+import score.BranchDB;
+import score.Context;
+import score.DictDB;
+
+import java.math.BigInteger;
+
+public class AddressBranchDictDB {
+
+ protected BranchDB
> legacyAddressDictDB;
+ protected BranchDB> addressDictDB;
+ protected BranchDB> migrationDB;
+
+ public AddressBranchDictDB(String id) {
+ this.legacyAddressDictDB = Context.newBranchDB(id, BigInteger.class);
+ this.addressDictDB = Context.newBranchDB(id + "_migrated", BigInteger.class);
+ this.migrationDB = Context.newBranchDB(id + "_migration_db", Boolean.class);
+ }
+
+ private BigInteger getLegacy(Address address, BigInteger key) {
+ return legacyAddressDictDB.at(address).getOrDefault(key, BigInteger.ZERO);
+ }
+
+ public Boolean isMigrated(Address address, BigInteger key) {
+ return migrationDB.at(address).getOrDefault(key, false);
+ }
+
+ public BigInteger get(NetworkAddress address, BigInteger id, boolean readonly) {
+ BigInteger total = addressDictDB.at(address.toString()).getOrDefault(id, BigInteger.ZERO);
+ if (address.account().startsWith("hx") || address.account().startsWith("cx")) {
+ Address iconAddr = Address.fromString(address.account());
+ if (!isMigrated(iconAddr, id)) {
+ total = total.add(getLegacy(iconAddr, id));
+ if (!readonly) {
+ migrationDB.at(iconAddr).set(id, true);
+ }
+ }
+ }
+
+ return total;
+ }
+
+ public void set(NetworkAddress address, BigInteger id, BigInteger value) {
+ addressDictDB.at(address.toString()).set(id, value);
+ }
+
+}
diff --git a/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/StakedLPImpl.java b/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/StakedLPImpl.java
index 4d3366ef5..3e38292ec 100644
--- a/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/StakedLPImpl.java
+++ b/core-contracts/StakedLP/src/main/java/network/balanced/score/core/stakedlp/StakedLPImpl.java
@@ -35,8 +35,7 @@
public class StakedLPImpl implements StakedLP {
- final static AddressBranchDictDB poolStakedDetails = new AddressBranchDictDB<>("poolStakeDetails",
- BigInteger.class);
+ final static AddressBranchDictDB poolStakedDetails = new AddressBranchDictDB("poolStakeDetails");
private static final DictDB totalStakedAmount = Context.newDictDB("totalStaked",
BigInteger.class);
@@ -125,13 +124,13 @@ public void setRewards(Address rewards) {
@External(readonly = true)
public BigInteger balanceOf(Address _owner, BigInteger _id) {
NetworkAddress owner = new NetworkAddress(NATIVE_NID, _owner.toString());
- return poolStakedDetails.at(owner).getOrDefault(_id, BigInteger.ZERO);
+ return poolStakedDetails.get(owner, _id, true);
}
@External(readonly = true)
public BigInteger xBalanceOf(String _owner, BigInteger _id) {
NetworkAddress owner = NetworkAddress.valueOf(_owner, NATIVE_NID);
- return poolStakedDetails.at(owner).getOrDefault(_id, BigInteger.ZERO);
+ return poolStakedDetails.get(owner, _id, true);
}
@External(readonly = true)
@@ -160,7 +159,8 @@ public void unstake(BigInteger id, BigInteger value) {
private void unstake(BigInteger id, NetworkAddress user, BigInteger value) {
Context.require(value.compareTo(BigInteger.ZERO) > 0, "StakedLP: Cannot unstake less than zero value");
- BigInteger previousBalance = poolStakedDetails.at(user).getOrDefault(id, BigInteger.ZERO);
+ BigInteger previousBalance = poolStakedDetails.get(user, id, false);
+
BigInteger previousTotal = totalStaked(id);
String poolName = getSourceName(id);
@@ -171,7 +171,7 @@ private void unstake(BigInteger id, NetworkAddress user, BigInteger value) {
BigInteger newTotal = previousTotal.subtract(value);
Context.require(newBalance.signum() >= 0 && newTotal.signum() >= 0, "StakedLP: New staked balance of user and" +
" total amount can't be negative");
- poolStakedDetails.at(user).set(id, newBalance);
+ poolStakedDetails.set(user, id, newBalance);
totalStakedAmount.set(id, newTotal);
Unstake(user.toString(), id, value);
@@ -263,11 +263,11 @@ private void stake(NetworkAddress user, BigInteger id, BigInteger value) {
"StakedLP: Cannot stake less than zero, value to stake " + value);
String poolName = getSourceName(id);
// Compute and store changes
- BigInteger previousBalance = poolStakedDetails.at(user).getOrDefault(id, BigInteger.ZERO);
+ BigInteger previousBalance = poolStakedDetails.get(user, id, false);
BigInteger previousTotal = totalStaked(id);
BigInteger newBalance = previousBalance.add(value);
BigInteger newTotal = previousTotal.add(value);
- poolStakedDetails.at(user).set(id, newBalance);
+ poolStakedDetails.set(user, id, newBalance);
totalStakedAmount.set(id, newTotal);
Stake(user.toString(), id, value);
diff --git a/core-contracts/StakedLP/src/test/java/network/balanced/score/core/stakedlp/DBTest.java b/core-contracts/StakedLP/src/test/java/network/balanced/score/core/stakedlp/DBTest.java
new file mode 100644
index 000000000..d7295dd85
--- /dev/null
+++ b/core-contracts/StakedLP/src/test/java/network/balanced/score/core/stakedlp/DBTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2022-2022 Balanced.network.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package network.balanced.score.core.stakedlp;
+
+import com.iconloop.score.test.Account;
+import com.iconloop.score.test.Score;
+import com.iconloop.score.test.ServiceManager;
+import com.iconloop.score.test.TestBase;
+
+import foundation.icon.xcall.NetworkAddress;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import score.Address;
+
+import java.math.BigInteger;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class DBTest extends TestBase {
+
+ private static final ServiceManager sm = getServiceManager();
+ private static final Account owner = sm.createAccount();
+ private static Score dummyScore;
+
+ public static class DummyScore extends AddressBranchDictDB {
+
+ public DummyScore() {
+ super("test");
+ }
+
+ public void setLegacy(Address address, BigInteger key, BigInteger value) {
+ legacyAddressDictDB.at(address).set(key, value);
+ }
+ }
+
+ @BeforeAll
+ public static void setup() throws Exception {
+ dummyScore = sm.deploy(owner, DummyScore.class);
+ }
+
+ @Test
+ public void onlyLegacyValue() {
+ // Arrange
+ Address user = sm.createAccount().getAddress();
+ BigInteger id = BigInteger.ONE;
+ BigInteger value = BigInteger.TEN;
+ dummyScore.invoke(owner, "setLegacy", user, id, value);
+
+ // Act
+ BigInteger balance = (BigInteger) dummyScore.call("get", new NetworkAddress("test", user), id, true);
+
+ // Assert
+ assertEquals(balance, value);
+ }
+
+ @Test
+ public void bothValues() {
+ // Arrange
+ Address user = sm.createAccount().getAddress();
+ BigInteger id = BigInteger.ONE;
+ BigInteger legacyValue = BigInteger.TEN;
+ BigInteger value = BigInteger.TWO;
+ dummyScore.invoke(owner, "setLegacy", user, id, legacyValue);
+ dummyScore.invoke(owner, "set", new NetworkAddress("test", user), id, value);
+
+ // Act
+ BigInteger balance = (BigInteger) dummyScore.call("get", new NetworkAddress("test", user), id, true);
+
+ // Assert
+ assertEquals(balance, legacyValue.add(value));
+ }
+
+ @Test
+ public void migrateValue() {
+ // Arrange
+ Address user = sm.createAccount().getAddress();
+ BigInteger id = BigInteger.ONE;
+ BigInteger legacyValue = BigInteger.TEN;
+ BigInteger value = BigInteger.TWO;
+ dummyScore.invoke(owner, "setLegacy", user, id, legacyValue);
+ dummyScore.invoke(owner, "set", new NetworkAddress("test", user), id, value);
+
+ // Act
+ dummyScore.invoke(owner, "get", new NetworkAddress("test", user), id, false);
+
+ // Assert
+ // In a real scenario set would be called, but for this the value is simply
+ // marked as migrated and wont be used anymore
+ BigInteger balance = (BigInteger) dummyScore.call("get", new NetworkAddress("test", user), id, true);
+ assertEquals(balance, value);
+ }
+
+ @Test
+ public void migrateContractValue() {
+ // Arrange
+ Address user = dummyScore.getAddress();
+ BigInteger id = BigInteger.ONE;
+ BigInteger legacyValue = BigInteger.TEN;
+ BigInteger value = BigInteger.TWO;
+ dummyScore.invoke(owner, "setLegacy", user, id, legacyValue);
+ dummyScore.invoke(owner, "set", new NetworkAddress("test", user), id, value);
+
+ // Act
+ dummyScore.invoke(owner, "get", new NetworkAddress("test", user), id, false);
+
+ // Assert
+ // In a real scenario set would be called, but for this the value is simply
+ // marked as migrated and wont be used anymore
+ BigInteger balance = (BigInteger) dummyScore.call("get", new NetworkAddress("test", user), id, true);
+ assertEquals(balance, value);
+ }
+
+ @Test
+ public void onlyNew() {
+ // Arrange
+ Address user = sm.createAccount().getAddress();
+ BigInteger id = BigInteger.ONE;
+ BigInteger value = BigInteger.TWO;
+ dummyScore.invoke(owner, "set", new NetworkAddress("test", user), id, value);
+
+ // Act
+ BigInteger balance = (BigInteger) dummyScore.call("get", new NetworkAddress("test", user), id, true);
+
+ // Assert
+ assertEquals(balance, value);
+ }
+
+ @Test
+ public void networkAddress() {
+ // Arrange
+ NetworkAddress user = new NetworkAddress("test", "test");
+ BigInteger id = BigInteger.ONE;
+ BigInteger value = BigInteger.TWO;
+ dummyScore.invoke(owner, "set", user, id, value);
+
+ // Act
+ BigInteger balance = (BigInteger) dummyScore.call("get", user, id, true);
+
+ // Assert
+ assertEquals(balance, value);
+ }
+
+}
diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/AddressBranchDictDB.java b/score-lib/src/main/java/network/balanced/score/lib/utils/AddressBranchDictDB.java
deleted file mode 100644
index c2d097f23..000000000
--- a/score-lib/src/main/java/network/balanced/score/lib/utils/AddressBranchDictDB.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package network.balanced.score.lib.utils;
-
-import foundation.icon.xcall.NetworkAddress;
-import score.Address;
-import score.BranchDB;
-import score.Context;
-import score.DictDB;
-
-
-public class AddressBranchDictDB {
-
- private BranchDB> legacyAddressDictDB;
- private BranchDB> addressDictDB;
-
- public AddressBranchDictDB(String id, Class valueClass) {
- this.legacyAddressDictDB = Context.newBranchDB(id, valueClass);
- this.addressDictDB = Context.newBranchDB(id + "_migrated", valueClass);
- }
-
-
- public DictDB at(NetworkAddress key) {
- DictDB value = addressDictDB.at(key.toString());
- if (value != null) {
- return value;
- }
-
- if (key.account().startsWith("hx") || key.account().startsWith("cx")) {
- value = legacyAddressDictDB.at(Address.fromString(key.account()));
- }
-
-
- return value;
- }
-
-}
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 4603f0633..38bfaa68d 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
@@ -17,7 +17,7 @@
package network.balanced.score.lib.utils;
public class Versions {
- public final static String BALN = "v1.1.0";
+ public final static String BALN = "v1.1.2";
public final static String DIVIDENDS = "v1.0.0";
public final static String LOANS = "v1.2.3";
public final static String RESERVE = "v1.0.0";
@@ -34,7 +34,7 @@ public class Versions {
public final static String GOVERNANCE = "v1.0.2";
public final static String REBALANCING = "v1.0.0";
public final static String ROUTER = "v1.1.8";
- public final static String STAKEDLP = "v1.0.8";
+ public final static String STAKEDLP = "v1.0.9";
public final static String BOOSTED_BALN = "v1.1.0";
public final static String BRIBING = "v1.0.1";
public final static String BALANCED_OTC = "v1.0.0";