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

feat: Update stakedLP storage with migrations #471

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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<Address, DictDB<BigInteger, BigInteger>> legacyAddressDictDB;
protected BranchDB<String, DictDB<BigInteger, BigInteger>> addressDictDB;
protected BranchDB<Address, DictDB<BigInteger, Boolean>> 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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@

public class StakedLPImpl implements StakedLP {

final static AddressBranchDictDB<BigInteger, BigInteger> poolStakedDetails = new AddressBranchDictDB<>("poolStakeDetails",
BigInteger.class);
final static AddressBranchDictDB poolStakedDetails = new AddressBranchDictDB("poolStakeDetails");

private static final DictDB<BigInteger, BigInteger> totalStakedAmount = Context.newDictDB("totalStaked",
BigInteger.class);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";
Expand Down
Loading