diff --git a/core-contracts/Bribing/build.gradle b/core-contracts/Bribing/build.gradle index b849e64c6..63d3794f9 100644 --- a/core-contracts/Bribing/build.gradle +++ b/core-contracts/Bribing/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation Dependencies.javaeeScorex implementation Dependencies.minimalJson implementation project(':score-lib') + implementation 'xyz.venture23:xcall-lib:2.1.0' testImplementation Dependencies.javaeeUnitTest testImplementation Dependencies.javaeeTokens diff --git a/core-contracts/Bribing/src/main/java/network/balanced/score/core/bribing/BribingImpl.java b/core-contracts/Bribing/src/main/java/network/balanced/score/core/bribing/BribingImpl.java index cb041688a..3f4cb21d4 100644 --- a/core-contracts/Bribing/src/main/java/network/balanced/score/core/bribing/BribingImpl.java +++ b/core-contracts/Bribing/src/main/java/network/balanced/score/core/bribing/BribingImpl.java @@ -16,7 +16,10 @@ package network.balanced.score.core.bribing; -import network.balanced.score.lib.utils.Versions; +import foundation.icon.xcall.NetworkAddress; +import network.balanced.score.lib.interfaces.BribingXCall; +import network.balanced.score.lib.interfaces.GovernanceXCall; +import network.balanced.score.lib.utils.*; import score.*; import score.annotation.External; @@ -29,7 +32,9 @@ import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import com.eclipsesource.json.JsonValue; +import score.annotation.Optional; +import static network.balanced.score.lib.utils.BalancedAddressManager.getXCall; import static network.balanced.score.lib.utils.Check.*; import static network.balanced.score.lib.utils.Constants.MICRO_SECONDS_IN_A_DAY; import static network.balanced.score.lib.utils.Constants.EXA; @@ -51,7 +56,9 @@ public class BribingImpl implements Bribing { //Source->bribeToken->period public static final BranchDB> activePeriod = Context.newBranchDB("activePeriod", BigInteger.class); //userAddress->Source->bribeToken->timeOfLastClaim - public static final BranchDB>> lastUserClaim = Context.newBranchDB("lastUserClaim", BigInteger.class); + //public static final BranchDB>> lastUserClaim = Context.newBranchDB("lastUserClaim", BigInteger.class); + public static final NetworkAddressBranchedStringBranchDictDB lastUserClaim = new NetworkAddressBranchedStringBranchDictDB<>("lastUserClaim", BigInteger.class); + public static final BranchDB> bribesPerSource = Context.newBranchDB("bribesPerSource", Address.class); public static final BranchDB> sourcesPerBribe = Context.newBranchDB("sourcesPerBribe", String.class); @@ -61,7 +68,9 @@ public class BribingImpl implements Bribing { private final VarDB currentVersion = Context.newVarDB("version", String.class); private final VarDB migrationPeriod = Context.newVarDB("migration_period", BigInteger.class); - private class SourceStatus { + public static String NATIVE_NID; + + private static class SourceStatus { BigInteger period; BigInteger bribesPerToken; } @@ -78,6 +87,7 @@ public BribingImpl(Address rewards) { Context.revert("Can't Update same version of code"); } this.currentVersion.set(Versions.BRIBING); + NATIVE_NID = Context.call(String.class, getXCall(), "getNetworkId"); } @External(readonly=true) @@ -148,7 +158,14 @@ public BigInteger getFutureBribe(String source, Address bribeToken, BigInteger p @External(readonly=true) public BigInteger claimable(Address user, String source, Address bribeToken) { - return getBribesAmount(user, source, bribeToken, true); + String networkAddress = new NetworkAddress(NATIVE_NID, user).toString(); + return getBribesAmount(networkAddress, source, bribeToken, true); + } + + @External(readonly=true) + public BigInteger xClaimable(String user, String source, Address bribeToken) { + String networkAddress = NetworkAddress.valueOf(user, NATIVE_NID).toString(); + return getBribesAmount(networkAddress, source, bribeToken, true); } @External @@ -159,13 +176,30 @@ public void updatePeriod(String source, Address bribeToken) { @External public void claimBribe(String source, Address bribeToken) { Address user = Context.getCaller(); - BigInteger amount = getBribesAmount(user, source, bribeToken, false); - Context.require(amount.compareTo(BigInteger.ZERO) > 0, user.toString() + " has no bribe in " + bribeToken.toString() + " to claim for source: " + source); + String networkAddress = new NetworkAddress(NATIVE_NID, user).toString(); + BigInteger amount = getBribesAmount(networkAddress, source, bribeToken, false); + Context.require(amount.compareTo(BigInteger.ZERO) > 0, user + " has no bribe in " + bribeToken.toString() + " to claim for source: " + source); BigInteger prevClaims = claimsPerSource.at(source).getOrDefault(bribeToken, BigInteger.ZERO); claimsPerSource.at(source).set(bribeToken, prevClaims.add(amount)); Context.call(bribeToken, "transfer", user, amount, new byte[0]); } + @External + public void handleCallMessage(String _from, byte[] _data, @Optional String[] _protocols) { + Check.checkStatus(); + only(getXCall()); + XCallUtils.verifyXCallProtocols(_from, _protocols); + BribingXCall.process(this, _from, _data); + } + + public void xClaimTo(String from, String source, Address bribeToken) { + BigInteger amount = getBribesAmount(from, source, bribeToken, false); + Context.require(amount.compareTo(BigInteger.ZERO) > 0, from + " has no bribe in " + bribeToken.toString() + " to claim for source: " + source); + BigInteger prevClaims = claimsPerSource.at(source).getOrDefault(bribeToken, BigInteger.ZERO); + claimsPerSource.at(source).set(bribeToken, prevClaims.add(amount)); + TokenTransfer.transfer(bribeToken, from, amount); + } + @External public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { Address token = Context.getCaller(); @@ -219,27 +253,26 @@ private void scheduledBribes(String source, Address bribeToken, BigInteger total add(source, bribeToken); } - private BigInteger getBribesAmount(Address user, String source, Address bribeToken, boolean readonly) { + private BigInteger getBribesAmount(String user, String source, Address bribeToken, boolean readonly) { SourceStatus status = updateSource(source, bribeToken, readonly); - DictDB lastUserClaim = BribingImpl.lastUserClaim.at(user).at(source); - if (lastUserClaim.getOrDefault(bribeToken, BigInteger.ZERO).compareTo(status.period) >= 0) { + NetworkAddress userNetworkAddress = NetworkAddress.valueOf(user, NATIVE_NID); + BigInteger lastUserClaimAmount = BribingImpl.lastUserClaim.getOrDefault(userNetworkAddress, source, bribeToken, BigInteger.ZERO); + if (lastUserClaimAmount.compareTo(status.period) >= 0) { return BigInteger.ZERO; } if (!readonly) { - lastUserClaim.set(bribeToken, status.period); + lastUserClaim.set(userNetworkAddress, source, bribeToken, status.period); } - BigInteger lastVote = Context.call(BigInteger.class, rewards.get(), "getLastUserVote", user, source); + BigInteger lastVote = Context.call(BigInteger.class, rewards.get(), "getLastUserVoteV2", user, source); if (lastVote.compareTo(status.period) >= 0) { return BigInteger.ZERO; } BigInteger bias = calculateUserBias(user, source); - BigInteger amount = bias.multiply(status.bribesPerToken).divide(EXA); - - return amount; + return bias.multiply(status.bribesPerToken).divide(EXA); } private SourceStatus updateSource(String source, Address bribeToken, boolean readOnly) { @@ -298,12 +331,12 @@ public BigInteger getSourceBias(String source, BigInteger period) { } - public Map getUserSlope(Address user, String source) { - Map userSlope = (Map)Context.call(rewards.get(), "getUserSlope", user, source); + public Map getUserSlope(String user, String source) { + Map userSlope = (Map)Context.call(rewards.get(), "getUserSlopeV2", user, source); return userSlope; } - public BigInteger calculateUserBias(Address user, String source) { + public BigInteger calculateUserBias(String user, String source) { BigInteger period = getCurrentPeriod(); Map userSlope = getUserSlope(user, source); BigInteger end = userSlope.get("end"); diff --git a/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTest.java b/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTest.java index 1b0f3ce86..92efc19e9 100644 --- a/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTest.java +++ b/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTest.java @@ -27,6 +27,7 @@ import java.math.BigInteger; import java.util.Map; +import foundation.icon.xcall.NetworkAddress; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; @@ -55,9 +56,9 @@ public void addReward() { // Act addBribe(source, amount); - when(rewards.mock.getLastUserVote(user.getAddress(), source)).thenReturn(startPeriod.add(BigInteger.ONE)); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source)).thenReturn(startPeriod.add(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user.getAddress(), source); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source); assertEquals(BigInteger.ZERO, bribing.call("claimable", user.getAddress(), source, bribeToken.getAddress())); @@ -103,8 +104,8 @@ public void claimBribe() { addBribe(source, amount); // Assert - when(rewards.mock.getLastUserVote(user.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user.getAddress(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source); sm.getBlock().increase(WEEK); doReturn(totalWeight).when(bribingSpy).getSourceBias(source, getPeriod()); @@ -131,8 +132,8 @@ public void claimBribe_carryUnclaimed() { addBribe(source, amount); // Assert - when(rewards.mock.getLastUserVote(user.getAddress(), source)).thenReturn(startPeriod.add(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user.getAddress(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source)).thenReturn(startPeriod.add(BigInteger.ONE)); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source); sm.getBlock().increase(WEEK); doReturn(totalWeight).when(bribingSpy).getSourceBias(source, getPeriod()); @@ -168,8 +169,8 @@ public void claimBribe_twice() { // Act addBribe(source, amount); - when(rewards.mock.getLastUserVote(user.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user.getAddress(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), source); sm.getBlock().increase(WEEK); doReturn(totalWeight).when(bribingSpy).getSourceBias(source, getPeriod());; @@ -210,10 +211,10 @@ public void scheduledBribes() { scheduledBribes(source, total, amounts); // Assert - when(rewards.mock.getLastUserVote(user1.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user1.getAddress(), source); - when(rewards.mock.getLastUserVote(user2.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); - doReturn(userWeight).when(bribingSpy).calculateUserBias(user2.getAddress(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user1.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user1.getAddress()).toString(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user2.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + doReturn(userWeight).when(bribingSpy).calculateUserBias(new NetworkAddress(NATIVE_NID, user2.getAddress()).toString(), source); for (int i = 0; i < 4; i++) { sm.getBlock().increase(WEEK); @@ -286,10 +287,10 @@ public void liveDataTest() { "slope", new BigInteger("2c9bb4a", 16) ); - doReturn(user1Slope).when(bribingSpy).getUserSlope(user1.getAddress(), source); - doReturn(user2Slope).when(bribingSpy).getUserSlope(user2.getAddress(), source); - when(rewards.mock.getLastUserVote(user1.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); - when(rewards.mock.getLastUserVote(user2.getAddress(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + doReturn(user1Slope).when(bribingSpy).getUserSlope(new NetworkAddress(NATIVE_NID, user1.getAddress()).toString(), source); + doReturn(user2Slope).when(bribingSpy).getUserSlope(new NetworkAddress(NATIVE_NID, user2.getAddress()).toString(), source); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user1.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); + when(rewards.mock.getLastUserVoteV2(new NetworkAddress(NATIVE_NID, user2.getAddress()).toString(), source)).thenReturn(startPeriod.subtract(BigInteger.ONE)); // Act doReturn(period.subtract(WEEK_IN_MS)).when(bribingSpy).getBlockTime(); diff --git a/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTestBase.java b/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTestBase.java index 80afb2a3b..87929a1a6 100644 --- a/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTestBase.java +++ b/core-contracts/Bribing/src/test/java/network/balanced/score/core/bribing/BribingImplTestBase.java @@ -24,7 +24,12 @@ import network.balanced.score.lib.interfaces.tokens.*; import network.balanced.score.lib.structs.BalancedAddresses; import network.balanced.score.lib.test.UnitTest; +import network.balanced.score.lib.test.integration.Balanced; +import network.balanced.score.lib.test.mock.MockBalanced; import network.balanced.score.lib.test.mock.MockContract; +import network.balanced.score.lib.utils.BalancedAddressManager; +import network.balanced.score.lib.utils.Names; +import score.Context; import java.math.BigInteger; import java.util.Map; @@ -51,13 +56,22 @@ class BribingImplTestBase extends UnitTest { protected MockContract rewards; protected MockContract bribeToken; + protected MockContract xCall; + protected MockContract governance; + private MockBalanced balanced; protected Score bribing; protected BribingImpl bribingSpy; + public final String NATIVE_NID = "0x1.ICON"; + protected void setupBase() throws Exception { - rewards = new MockContract<>(RewardsScoreInterface.class, sm, owner); + balanced = new MockBalanced(sm, owner); + rewards = balanced.rewards; + governance = balanced.governance; bribeToken = new MockContract<>(IRC2ScoreInterface.class, sm, owner); + xCall = balanced.xCall; + when(xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); bribing = sm.deploy(owner, BribingImpl.class, rewards.getAddress()); bribingSpy = (BribingImpl) spy(bribing.getInstance()); diff --git a/core-contracts/Dex/build.gradle b/core-contracts/Dex/build.gradle index 67c301af5..558894a36 100644 --- a/core-contracts/Dex/build.gradle +++ b/core-contracts/Dex/build.gradle @@ -54,7 +54,6 @@ dependencies { testImplementation Dependencies.mockitoCore testImplementation Dependencies.mockitoInline - testImplementation project(':test-lib') testImplementation Dependencies.junitJupiter testRuntimeOnly Dependencies.junitJupiterEngine diff --git a/core-contracts/Dex/src/main/java/network/balanced/score/core/dex/DexImpl.java b/core-contracts/Dex/src/main/java/network/balanced/score/core/dex/DexImpl.java index 2e101bb50..7ec63e753 100644 --- a/core-contracts/Dex/src/main/java/network/balanced/score/core/dex/DexImpl.java +++ b/core-contracts/Dex/src/main/java/network/balanced/score/core/dex/DexImpl.java @@ -144,6 +144,7 @@ public void xTokenFallback(String _from, BigInteger _value, byte[] _data) { require(_value.compareTo(BigInteger.ZERO) > 0, TAG + ": Invalid token transfer value"); if (method.equals("_deposit")) { + JsonObject params = json.get("params").asObject(); String to = _from; if (params.get("address") != null) { diff --git a/core-contracts/Dividends/build.gradle b/core-contracts/Dividends/build.gradle index fb3175029..7d6c62c06 100644 --- a/core-contracts/Dividends/build.gradle +++ b/core-contracts/Dividends/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation Dependencies.javaeeScorex implementation Dependencies.minimalJson implementation project(':score-lib') + implementation 'xyz.venture23:xcall-lib:2.1.0' testImplementation Dependencies.javaeeUnitTest testImplementation Dependencies.javaeeTokens diff --git a/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsImpl.java b/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsImpl.java index 4f32e28f3..3bf3834f4 100644 --- a/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsImpl.java +++ b/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsImpl.java @@ -16,11 +16,12 @@ package network.balanced.score.core.dividends; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.interfaces.Dividends; +import network.balanced.score.lib.interfaces.DividendsXCall; import network.balanced.score.lib.structs.DistributionPercentage; import network.balanced.score.lib.structs.PrepDelegations; -import network.balanced.score.lib.utils.Names; -import network.balanced.score.lib.utils.Versions; +import network.balanced.score.lib.utils.*; import score.*; import score.annotation.EventLog; import score.annotation.External; @@ -28,6 +29,7 @@ import scorex.util.ArrayList; import scorex.util.HashMap; +import java.lang.Math; import java.math.BigInteger; import java.util.List; import java.util.Map; @@ -67,10 +69,11 @@ public class DividendsImpl implements Dividends { private static final VarDB dividendsEnabledToStakedBalnDay = Context.newVarDB(DIVIDENDS_ENABLED_TO_STAKED_BALN_ONLY_DAY, BigInteger.class); - private static final BranchDB> accruedDividends = - Context.newBranchDB(ACCRUED_DIVIDENDS, BigInteger.class); + private static final NetworkAddressBranchDictDB accruedDividends = + new NetworkAddressBranchDictDB<>(ACCRUED_DIVIDENDS, BigInteger.class); private final VarDB currentVersion = Context.newVarDB(VERSION, String.class); + public static String NATIVE_NID; public DividendsImpl(@Optional Address _governance) { if (governance.get() == null) { @@ -90,6 +93,7 @@ public DividendsImpl(@Optional Address _governance) { Context.revert("Can't Update same version of code"); } currentVersion.set(Versions.DIVIDENDS); + NATIVE_NID = (String) Context.call(getXCall(), "getNetworkId"); } @External(readonly = true) @@ -118,6 +122,10 @@ public void setTimeOffset(BigInteger deltaTime) { timeOffset.set(deltaTime); } + protected String getStringNetworkAddress(Address address){ + return new NetworkAddress(NATIVE_NID, address).toString(); + } + @External public void setDividendsOnlyToStakedBalnDay(BigInteger day) { onlyGovernance(); @@ -131,6 +139,7 @@ public BigInteger getDividendsOnlyToStakedBalnDay() { return dividendsEnabledToStakedBalnDay.getOrDefault(BigInteger.ZERO); } + //verify if we need this method for network address @External(readonly = true) public Map getBalances() { Address address = Context.getAddress(); @@ -315,7 +324,7 @@ public void transferDaofundDividends(@Optional int _start, @Optional int _end) { Map dividends = getDividendsForDaoFund(BigInteger.valueOf(i), acceptedTokensList, daofund); if (dividends.size() != 0) { - setClaimed(daofund, BigInteger.valueOf(i)); + setClaimed(daofund.toString(), BigInteger.valueOf(i)); } totalDividends = addDividends(totalDividends, dividends, acceptedTokensList); @@ -327,7 +336,7 @@ public void transferDaofundDividends(@Optional int _start, @Optional int _end) { if (totalDividends.containsKey(token.toString()) && totalDividends.get(token.toString()).signum() > 0) { nonZeroTokens.put(token.toString(), totalDividends.get(token.toString())); - sendToken(daofund, totalDividends.get(token.toString()), token, "Daofund dividends"); + sendToken(daofund.toString(), totalDividends.get(token.toString()), token, "Daofund dividends"); } } if (nonZeroTokens.size() > 0) { @@ -335,7 +344,7 @@ public void transferDaofundDividends(@Optional int _start, @Optional int _end) { } } - protected BigInteger calculateAccruedDividends(Address token, Address user, boolean readonly) { + protected BigInteger calculateAccruedDividends(Address token, String user, boolean readonly) { BigInteger accruedDividends = BigInteger.ZERO; BigInteger balance = getBalnBalance(user); BigInteger bbalnBalance = userBalance.getOrDefault(user, BigInteger.ZERO); @@ -352,43 +361,67 @@ protected BigInteger calculateAccruedDividends(Address token, Address user, bool @External(readonly = true) public Map getUnclaimedDividends(Address user) { + String networkAddress = getStringNetworkAddress(user); + return getUnclaimedDividendsInternal(networkAddress); + } + + @External(readonly = true) + public Map getUnclaimedDividendsV2(String user) { + String networkAddress = NetworkAddress.valueOf(user, NATIVE_NID).toString(); + return getUnclaimedDividendsInternal(networkAddress); + } + + private Map getUnclaimedDividendsInternal(String user) { Map totalDividends = new HashMap<>(); int size = acceptedTokens.size(); - DictDB userAccruedDividends = accruedDividends.at(user); for (int i = 0; i < size; i++) { Address token = acceptedTokens.get(i); - BigInteger accruedDividends = calculateAccruedDividends(token, user, true); - BigInteger prevAccruedDividends = userAccruedDividends.getOrDefault(token, BigInteger.ZERO); - BigInteger totalDivs = accruedDividends.add(prevAccruedDividends); + BigInteger calcAccruedDividends = calculateAccruedDividends(token, user, true); + BigInteger prevAccruedDividends = accruedDividends.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); + BigInteger totalDivs = calcAccruedDividends.add(prevAccruedDividends); totalDividends.put(token.toString(), totalDivs); } return totalDividends; } + @External + public void handleCallMessage(String _from, byte[] _data, @Optional String[] _protocols) { + Check.checkStatus(); + only(getXCall()); + XCallUtils.verifyXCallProtocols(_from, _protocols); + DividendsXCall.process(this, _from, _data); + } + + public void xClaimDividends(String from){ + claimDividendsInternal(from); + } + @External public void claimDividends() { - checkStatus(); - routeFees(); Address user = Context.getCaller(); + claimDividendsInternal(getStringNetworkAddress(user)); + } + private void claimDividendsInternal(String user){ + checkStatus(); + routeFees(); int size = acceptedTokens.size(); - DictDB userAccruedDividends = accruedDividends.at(user); Map nonZeroTokens = new HashMap<>(); for (int i = 0; i < size; i++) { Address token = acceptedTokens.get(i); - BigInteger accruedDividends = calculateAccruedDividends(token, user, false); - BigInteger prevAccruedDividends = userAccruedDividends.getOrDefault(token, BigInteger.ZERO); - BigInteger totalDivs = accruedDividends.add(prevAccruedDividends); + BigInteger calcAccruedDividends = calculateAccruedDividends(token, user, false); + BigInteger prevAccruedDividends = accruedDividends.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); + BigInteger totalDivs = calcAccruedDividends.add(prevAccruedDividends); if (totalDivs.signum() > 0) { nonZeroTokens.put(token.toString(), totalDivs); - userAccruedDividends.set(token, null); + accruedDividends.set(NetworkAddress.valueOf(user), token, null); sendToken(user, totalDivs, token, "User dividends"); } } if (nonZeroTokens.size() > 0) { - Claimed(user, BigInteger.ZERO, BigInteger.ZERO, dividendsMapToJson(nonZeroTokens)); + ClaimedV2(user, BigInteger.ZERO, BigInteger.ZERO, dividendsMapToJson(nonZeroTokens)); } BigInteger bbalnBalance = getBBalnBalance(user); @@ -397,14 +430,22 @@ public void claimDividends() { DividendsTracker.setBBalnTotalSupply(getBoostedTotalSupply().add(bbalnBalance).subtract(prevBalance)); } + public void xClaim(String from, @Optional Integer _start, @Optional Integer _end){ + claimInternal(from, _start, _end); + } + @External public void claim(@Optional int _start, @Optional int _end) { + Address account = Context.getCaller(); + claimInternal(getStringNetworkAddress(account), _start, _end); + } + + private void claimInternal(String account, @Optional int _start, @Optional int _end) { checkStatus(); int[] value = checkStartEnd(_start, _end); int start = value[0]; int end = value[1]; - Address account = Context.getCaller(); Map totalDividends = new HashMap<>(); Address baln = getBaln(); @@ -434,12 +475,20 @@ public void claim(@Optional int _start, @Optional int _end) { } } if (nonZeroTokens.size() > 0) { - Claimed(account, BigInteger.valueOf(start), BigInteger.valueOf(end), dividendsMapToJson(nonZeroTokens)); + ClaimedV2(account, BigInteger.valueOf(start), BigInteger.valueOf(end), dividendsMapToJson(nonZeroTokens)); } } + public void xAccumulateDividends(String from, @Optional Integer _start, @Optional Integer _end){ + accumulateDividendsInternal(from, _start, _end); + } + @External public void accumulateDividends(Address user, @Optional int _start, @Optional int _end) { + accumulateDividendsInternal(getStringNetworkAddress(user), _start, _end); + } + + private void accumulateDividendsInternal(String user, @Optional int _start, @Optional int _end) { checkStatus(); int[] value = checkStartEnd(_start, _end); @@ -466,12 +515,11 @@ public void accumulateDividends(Address user, @Optional int _start, @Optional in totalDividends = addDividends(totalDividends, dividends, acceptedTokensList); } - DictDB userAccruedDividends = accruedDividends.at(user); for (Address token : acceptedTokensList) { if (totalDividends.containsKey(token.toString()) && totalDividends.get(token.toString()).signum() > 0) { - BigInteger accruedDividends = totalDividends.get(token.toString()); - BigInteger prevAccruedDividends = userAccruedDividends.getOrDefault(token, BigInteger.ZERO); - userAccruedDividends.set(token, accruedDividends.add(prevAccruedDividends)); + BigInteger calcAccruedDividends = totalDividends.get(token.toString()); + BigInteger prevAccruedDividends = accruedDividends.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); + accruedDividends.set(NetworkAddress.valueOf(user), token, calcAccruedDividends.add(prevAccruedDividends)); } } } @@ -481,9 +529,9 @@ public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { checkStatus(); Address token = Context.getCaller(); Context.require(arrayDbContains(acceptedTokens, token), "Dividends contract does not accept " + token); - + String daoFundNetworkAddress = getStringNetworkAddress(getDaofund()); if (getBoostedTotalSupply().equals(BigInteger.ZERO)) { - sendToken(getDaofund(), _value, token, "Daofund dividends"); + sendToken( daoFundNetworkAddress, _value, token, "Daofund dividends"); return; } @@ -492,31 +540,22 @@ public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { // update boosted total weight if the bbaln day is started DividendsTracker.updateBoostedTotalWeight(token, _value.subtract(dividendsToDaofund)); DividendsReceivedV2(_value, getDay(), _value + " tokens received as dividends token: " + token); - sendToken(getDaofund(), dividendsToDaofund, token, "Daofund dividends"); + sendToken( daoFundNetworkAddress, dividendsToDaofund, token, "Daofund dividends"); } - @External - public void updateBalnStake(Address user, BigInteger prevStakedBalance, BigInteger currentTotalSupply) { - checkStatus(); - only(getBaln()); - int size = acceptedTokens.size(); - DictDB userAccruedDividends = accruedDividends.at(user); - for (int i = 0; i < size; i++) { - Address token = acceptedTokens.get(i); - if (DividendsTracker.balnRewardsClaimed(user, token)) { - return; - } - - BigInteger accruedDividends = DividendsTracker.updateUserData(token, user, prevStakedBalance, false); - BigInteger prevAccruedDividends = userAccruedDividends.getOrDefault(token, BigInteger.ZERO); - userAccruedDividends.set(token, prevAccruedDividends.add(accruedDividends)); - } - - DividendsTracker.setTotalSupply(currentTotalSupply); + @External(readonly = true) + public Map getUserDividendsV2(String _account, @Optional int _start, @Optional int _end) { + String user = NetworkAddress.valueOf(_account, NATIVE_NID).toString(); + return getUserDividendsInternal(user, _start, _end); } @External(readonly = true) public Map getUserDividends(Address _account, @Optional int _start, @Optional int _end) { + String user = getStringNetworkAddress(_account); + return getUserDividendsInternal(user, _start, _end); + } + + private Map getUserDividendsInternal(String _account, int _start, int _end){ int[] value = checkStartEnd(_start, _end); int start = value[0]; int end = value[1]; @@ -607,7 +646,7 @@ public Map dividendsAt(BigInteger _day) { } @External - public void onKick(Address user) { + public void onKick(String user) { checkStatus(); only(getBoostedBaln()); BigInteger userPrevBalance = userBalance.getOrDefault(user, BigInteger.ZERO); @@ -616,11 +655,11 @@ public void onKick(Address user) { updateUserDividends(user, userPrevBalance); userBalance.set(user, null); DividendsTracker.setBBalnTotalSupply(getBoostedTotalSupply().subtract(userPrevBalance)); - UserKicked(user, "user kicked".getBytes()); + UserKickedV2(user, "user kicked".getBytes()); } @External - public void onBalanceUpdate(Address user, BigInteger bBalnBalance) { + public void onBalanceUpdate(String user, BigInteger bBalnBalance) { checkStatus(); only(getBoostedBaln()); BigInteger prevBalance = userBalance.getOrDefault(user, BigInteger.ZERO); @@ -629,14 +668,13 @@ public void onBalanceUpdate(Address user, BigInteger bBalnBalance) { DividendsTracker.setBBalnTotalSupply(getBoostedTotalSupply().add(bBalnBalance).subtract(prevBalance)); } - private void updateUserDividends(Address user, BigInteger prevBalance) { - DictDB userAccruedDividends = accruedDividends.at(user); + private void updateUserDividends(String user, BigInteger prevBalance) { int size = acceptedTokens.size(); for (int i = 0; i < size; i++) { Address token = acceptedTokens.get(i); - BigInteger accruedDividends = DividendsTracker.updateBoostedUserData(token, user, prevBalance, false); - BigInteger prevAccruedDividends = userAccruedDividends.getOrDefault(token, BigInteger.ZERO); - userAccruedDividends.set(token, prevAccruedDividends.add(accruedDividends)); + BigInteger calcAccruedDividends = DividendsTracker.updateBoostedUserData(token, user, prevBalance, false); + BigInteger prevAccruedDividends = accruedDividends.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); + accruedDividends.set(NetworkAddress.valueOf(user), token, prevAccruedDividends.add(calcAccruedDividends)); } } @@ -660,7 +698,7 @@ private int[] checkStartEnd(int start, int end) { return new int[]{start, end}; } - private Map getDividendsForDay(Address account, BigInteger day, Address baln, Address dex, + private Map getDividendsForDay(String account, BigInteger day, Address baln, Address dex, BigInteger dividendsSwitchingDay, List
acceptedTokensList) { boolean claim = isClaimed(account, day); @@ -714,7 +752,7 @@ private Map getDividendsForDay(Address account, BigInteger d private Map getDividendsForDaoFund(BigInteger day, List
acceptedTokensList, Address dao) { - boolean claim = isClaimed(dao, day); + boolean claim = isClaimed(getStringNetworkAddress(dao), day); if (claim) { return Map.of(); } @@ -752,8 +790,8 @@ private Map addDividends(Map totalDivide return Map.of(); } - private void setClaimed(Address account, BigInteger day) { - DictDB claimedBitMap = Context.newDictDB(CLAIMED_BIT_MAP + account.toString(), + private void setClaimed(String account, BigInteger day) { + DictDB claimedBitMap = Context.newDictDB(CLAIMED_BIT_MAP + account, BigInteger.class); BigInteger claimedWordIndex = day.divide(TWO_FIFTY_SIX); BigInteger claimedBitIndex = day.remainder(TWO_FIFTY_SIX); @@ -763,8 +801,8 @@ private void setClaimed(Address account, BigInteger day) { claimedBitMap.getOrDefault(claimedWordIndex, BigInteger.ZERO).setBit(bitShift)); } - private boolean isClaimed(Address account, BigInteger day) { - DictDB claimedBitMap = Context.newDictDB(CLAIMED_BIT_MAP + account.toString(), + private boolean isClaimed(String account, BigInteger day) { + DictDB claimedBitMap = Context.newDictDB(CLAIMED_BIT_MAP + account, BigInteger.class); BigInteger claimedWordIndex = day.divide(TWO_FIFTY_SIX); BigInteger claimedBitIndex = day.remainder(TWO_FIFTY_SIX); @@ -776,17 +814,18 @@ private boolean isClaimed(Address account, BigInteger day) { return claimedWord.and(mask).equals(mask); } - private void sendToken(Address to, BigInteger amount, Address token, String msg) { - Context.call(token, "transfer", to, amount, new byte[0]); - FundTransfer(to, amount, msg + amount + " token sent to" + to); + private void sendToken(String to, BigInteger amount, Address token, String msg) { + TokenTransfer.transfer(token, to, amount); + FundTransferV2(to, amount, msg + amount + " token sent to" + to); } - private BigInteger getBalnBalance(Address user) { - return Context.call(BigInteger.class, getBaln(), "stakedBalanceOf", user); + + private BigInteger getBalnBalance(String user) { + return BigInteger.ZERO; } - private BigInteger getBBalnBalance(Address user) { - return Context.call(BigInteger.class, getBoostedBaln(), "balanceOf", user, BigInteger.ZERO); + private BigInteger getBBalnBalance(String user) { + return Context.call(BigInteger.class, getBoostedBaln(), "xBalanceOf", user, BigInteger.ZERO); } private void addInitialCategories() { @@ -819,6 +858,11 @@ public void FundTransfer(Address destination, BigInteger amount, String note) { } + @EventLog(indexed = 3) + public void FundTransferV2(String destination, BigInteger amount, String note) { + + } + @EventLog(indexed = 2) public void DividendsReceivedV2(BigInteger _amount, BigInteger _day, String _data) { @@ -829,8 +873,18 @@ public void Claimed(Address _address, BigInteger _start, BigInteger _end, String } + @EventLog(indexed = 1) + public void ClaimedV2(String _address, BigInteger _start, BigInteger _end, String _dividends) { + + } + @EventLog(indexed = 1) public void UserKicked(Address user, byte[] _data) { } + + @EventLog(indexed = 1) + public void UserKickedV2(String user, byte[] _data) { + + } } \ No newline at end of file diff --git a/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsTracker.java b/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsTracker.java index e75fa2be9..c1a5fe09d 100644 --- a/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsTracker.java +++ b/core-contracts/Dividends/src/main/java/network/balanced/score/core/dividends/DividendsTracker.java @@ -16,6 +16,10 @@ package network.balanced.score.core.dividends; +import foundation.icon.xcall.NetworkAddress; +import network.balanced.score.lib.utils.AddressDictDB; +import network.balanced.score.lib.utils.BranchedNetworkAddressDictDB; +import network.balanced.score.lib.utils.NetworkAddressBranchDictDB; import score.*; import java.math.BigInteger; @@ -24,32 +28,35 @@ import static network.balanced.score.lib.utils.Constants.EXA; public class DividendsTracker { - protected static final BranchDB> userWeight = Context.newBranchDB( + protected static final NetworkAddressBranchDictDB userWeight = new NetworkAddressBranchDictDB<>( "user_weight", BigInteger.class); private static final VarDB totalSupply = Context.newVarDB("balnSupply", BigInteger.class); private static final DictDB totalWeight = Context.newDictDB("running_total", BigInteger.class); - private static final BranchDB> boostedUserWeight = - Context.newBranchDB(BBALN_USER_WEIGHT, BigInteger.class); + private static final NetworkAddressBranchDictDB boostedUserWeight = + new NetworkAddressBranchDictDB<>(BBALN_USER_WEIGHT, BigInteger.class); private static final DictDB boostedTotalWeight = Context.newDictDB(BBALN_TOTAL_WEIGHT, BigInteger.class); - protected static final DictDB userBalance = Context.newDictDB(USER_BBALN_BALANCE, + + protected static final AddressDictDB userBalance = new AddressDictDB<>(USER_BBALN_BALANCE, BigInteger.class); + private static final VarDB boostedTotalSupply = Context.newVarDB(BBALN_SUPPLY, BigInteger.class); - protected static final BranchDB> balnRewardsClaimed = Context.newBranchDB( + + protected static final BranchedNetworkAddressDictDB balnRewardsClaimed = new BranchedNetworkAddressDictDB<>( "baln_to_bBaln_migration_check", Boolean.class); - public static BigInteger getUserWeight(Address user, Address token) { - return userWeight.at(user).getOrDefault(token, BigInteger.ZERO); + public static BigInteger getUserWeight(String user, Address token) { + return userWeight.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); } public static void setTotalSupply(BigInteger supply) { totalSupply.set(supply); } - public static BigInteger getUserBoostedWeight(Address user, Address token) { - return boostedUserWeight.at(user).getOrDefault(token, BigInteger.ZERO); + public static BigInteger getUserBoostedWeight(String user, Address token) { + return boostedUserWeight.getOrDefault(NetworkAddress.valueOf(user), token, BigInteger.ZERO); } public static BigInteger getBoostedTotalSupply() { @@ -68,28 +75,28 @@ public static BigInteger getBoostedTotalWeight(Address token) { return boostedTotalWeight.getOrDefault(token, BigInteger.ZERO); } - public static Boolean balnRewardsClaimed(Address user, Address token) { - return balnRewardsClaimed.at(token).getOrDefault(user, false); + public static Boolean balnRewardsClaimed(String user, Address token) { + return balnRewardsClaimed.at(token).getOrDefault(NetworkAddress.valueOf(user), false); } - public static BigInteger updateUserData(Address token, Address user, BigInteger prevBalance, + public static BigInteger updateUserData(Address token, String user, BigInteger prevBalance, boolean readOnlyContext) { BigInteger currentUserWeight = getUserWeight(user, token); BigInteger totalWeight = getTotalWeight(token); if (!readOnlyContext) { - userWeight.at(user).set(token, totalWeight); - balnRewardsClaimed.at(token).set(user, true); + userWeight.set(NetworkAddress.valueOf(user), token, totalWeight); + balnRewardsClaimed.at(token).set(NetworkAddress.valueOf(user), true); } return computeUserRewards(prevBalance, totalWeight, currentUserWeight); } - public static BigInteger updateBoostedUserData(Address token, Address user, BigInteger prevBalance, + public static BigInteger updateBoostedUserData(Address token, String user, BigInteger prevBalance, boolean readOnlyContext) { BigInteger currentUserWeight = getUserBoostedWeight(user, token); BigInteger totalWeight = getBoostedTotalWeight(token); if (!readOnlyContext) { - boostedUserWeight.at(user).set(token, totalWeight); + boostedUserWeight.set(NetworkAddress.valueOf(user), token, totalWeight); } return computeUserRewards(prevBalance, totalWeight, currentUserWeight); diff --git a/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestBase.java b/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestBase.java index baaa2341a..03ff36665 100644 --- a/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestBase.java +++ b/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestBase.java @@ -28,6 +28,7 @@ import java.util.Map; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; class DividendsImplTestBase extends UnitTest { protected static final ServiceManager sm = getServiceManager(); @@ -48,6 +49,8 @@ class DividendsImplTestBase extends UnitTest { protected static MockContract bBaln; protected static MockContract governance; + public final String NATIVE_NID = "0x1.ICON"; + protected Score dividendScore; protected void addBnusdFees(BigInteger amount) { @@ -75,9 +78,12 @@ protected void setupBase() throws Exception { baln = mockBalanced.baln; bBaln = mockBalanced.bBaln; governance = mockBalanced.governance; - + + when(mockBalanced.xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); dividendScore = sm.deploy(owner, DividendsImpl.class, governance.getAddress()); DividendsImpl dividendsSpy = (DividendsImpl) spy(dividendScore.getInstance()); dividendScore.setInstance(dividendsSpy); + + } } diff --git a/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestContinuousDividends.java b/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestContinuousDividends.java index 2cfd9a626..e9efe9970 100644 --- a/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestContinuousDividends.java +++ b/core-contracts/Dividends/src/test/java/network/balanced/score/core/dividends/DividendsImplTestContinuousDividends.java @@ -17,6 +17,7 @@ package network.balanced.score.core.dividends; import com.iconloop.score.test.Account; +import foundation.icon.xcall.NetworkAddress; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import score.Address; @@ -31,6 +32,7 @@ class DividendsImplTestContinuousDividends extends DividendsImplTestBase { private final BigInteger batchSize = BigInteger.TWO; + @BeforeEach void setup() throws Exception { sm.getBlock().increase(2 * DAY); @@ -50,6 +52,8 @@ void claimDividends_bbaln() { // Arrange Account staker1 = sm.createAccount(); Account staker2 = sm.createAccount(); + String staker1String = NetworkAddress.valueOf(staker1.getAddress().toString(), NATIVE_NID).toString(); + String staker2String = NetworkAddress.valueOf(staker2.getAddress().toString(), NATIVE_NID).toString(); when(baln.mock.stakedBalanceOf(staker1.getAddress())).thenReturn(BigInteger.ZERO); when(baln.mock.stakedBalanceOf(staker2.getAddress())).thenReturn(BigInteger.ZERO); @@ -64,8 +68,8 @@ void claimDividends_bbaln() { mockBBalnBalanceOf(staker1.getAddress(), staker1Balance); // Act - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1.getAddress(), staker1Balance); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2.getAddress(), staker2Balance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1String, staker1Balance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2String, staker2Balance); BigInteger expectedFees = BigInteger.TEN.pow(20); BigInteger expectedStakingFees = expectedFees.multiply(stakerPercentage).divide(ICX); @@ -109,10 +113,12 @@ void onKick_bbaln() { mockBBalnBalanceOf(staker2.getAddress(), staker2BBalnBalance); mockBBalnBalanceOf(staker1.getAddress(), staker1BBalnBalance); + String staker1String = NetworkAddress.valueOf(staker1.getAddress().toString(), NATIVE_NID).toString(); + String staker2String = NetworkAddress.valueOf(staker2.getAddress().toString(), NATIVE_NID).toString(); // Act - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1.getAddress(), staker1BBalnBalance); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2.getAddress(), staker2BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1String, staker1BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2String, staker2BBalnBalance); BigInteger loanAmount = BigInteger.TEN.pow(20); BigInteger dividendsForBBalnUser = loanAmount.multiply(stakerPercentage).divide(ICX); @@ -122,12 +128,12 @@ void onKick_bbaln() { BigInteger user2AccruedDividends = dividendsForBBalnUser.multiply(staker2BBalnBalance).divide(totalSupply); // Assert - mockStake(staker1.getAddress(), staker1BBalnBalance); - mockStake(staker2.getAddress(), staker2BBalnBalance); + mockStake(staker1.getAddress(), BigInteger.ZERO); + mockStake(staker2.getAddress(), BigInteger.ZERO); mockBBalnBalanceOf(staker2.getAddress(), staker2BBalnBalance); mockBBalnBalanceOf(staker1.getAddress(), staker1BBalnBalance); - dividendScore.invoke(bBaln.account, "onKick", staker1.getAddress()); + dividendScore.invoke(bBaln.account, "onKick", staker1String); dividendScore.invoke(staker1, "claimDividends"); dividendScore.invoke(staker2, "claimDividends"); @@ -147,6 +153,8 @@ void onBalanceUpdate_bbaln() { // Arrange Account staker1 = sm.createAccount(); Account staker2 = sm.createAccount(); + String staker1String = NetworkAddress.valueOf(staker1.getAddress().toString(), NATIVE_NID).toString(); + String staker2String = NetworkAddress.valueOf(staker2.getAddress().toString(), NATIVE_NID).toString(); when(baln.mock.stakedBalanceOf(staker1.getAddress())).thenReturn(BigInteger.ZERO); when(baln.mock.stakedBalanceOf(staker2.getAddress())).thenReturn(BigInteger.ZERO); @@ -161,8 +169,8 @@ void onBalanceUpdate_bbaln() { mockBBalnBalanceOf(staker1.getAddress(), staker1BBalnBalance); // Act - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1.getAddress(), staker1BBalnBalance); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2.getAddress(), staker2BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1String, staker1BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2String, staker2BBalnBalance); BigInteger loanAmount = BigInteger.TEN.pow(20); @@ -184,6 +192,8 @@ void getUnclaimedDividends_bbaln() { // Arrange Account staker1 = sm.createAccount(); Account staker2 = sm.createAccount(); + String staker1String = NetworkAddress.valueOf(staker1.getAddress().toString(), NATIVE_NID).toString(); + String staker2String = NetworkAddress.valueOf(staker2.getAddress().toString(), NATIVE_NID).toString(); when(baln.mock.stakedBalanceOf(staker1.getAddress())).thenReturn(BigInteger.ZERO); when(baln.mock.stakedBalanceOf(staker2.getAddress())).thenReturn(BigInteger.ZERO); @@ -197,8 +207,8 @@ void getUnclaimedDividends_bbaln() { mockBBalnBalanceOf(staker1.getAddress(), staker1BBalnBalance); // Act - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1.getAddress(), staker1BBalnBalance); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2.getAddress(), staker2BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1String, staker1BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2String, staker2BBalnBalance); BigInteger loanAmount = BigInteger.TEN.pow(20); addBnusdFeesAndMockDaoFund(loanAmount); @@ -224,8 +234,8 @@ void getUnclaimedDividends_bbaln() { BigInteger newStaker1BBalnBalance = BigInteger.valueOf(350).multiply(ICX); BigInteger newStaker2BBalnBalance = BigInteger.valueOf(100).multiply(ICX); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1.getAddress(), newStaker1BBalnBalance); - dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2.getAddress(), newStaker2BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker1String, newStaker1BBalnBalance); + dividendScore.invoke(bBaln.account, "onBalanceUpdate", staker2String, newStaker2BBalnBalance); addBnusdFees(loanAmount); // new total supply for bbaln @@ -258,7 +268,8 @@ private void mockStake(Address user, BigInteger stake) { } private void mockBBalnBalanceOf(Address user, BigInteger stake) { - when(bBaln.mock.balanceOf(eq(user), any(BigInteger.class))).thenReturn(stake); + String networkAddress = NetworkAddress.valueOf(user.toString(), NATIVE_NID).toString(); + when(bBaln.mock.xBalanceOf(eq(networkAddress), any(BigInteger.class))).thenReturn(stake); } } \ No newline at end of file diff --git a/core-contracts/Governance/build.gradle b/core-contracts/Governance/build.gradle index c8cb73ff8..4f735d79a 100644 --- a/core-contracts/Governance/build.gradle +++ b/core-contracts/Governance/build.gradle @@ -33,6 +33,7 @@ dependencies { implementation Dependencies.javaeeScorex implementation project(':score-lib') implementation Dependencies.minimalJson + implementation 'xyz.venture23:xcall-lib:2.1.0' testImplementation Dependencies.javaeeTokens testImplementation Dependencies.javaeeUnitTest diff --git a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/GovernanceImpl.java b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/GovernanceImpl.java index 534541bb7..a5d322d9f 100644 --- a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/GovernanceImpl.java +++ b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/GovernanceImpl.java @@ -16,16 +16,17 @@ package network.balanced.score.core.governance; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.core.governance.proposal.ProposalDB; import network.balanced.score.core.governance.proposal.ProposalManager; import network.balanced.score.core.governance.utils.ContractManager; import network.balanced.score.core.governance.utils.EmergencyManager; import network.balanced.score.core.governance.utils.SetupManager; import network.balanced.score.lib.interfaces.Governance; +import network.balanced.score.lib.interfaces.GovernanceXCall; +import network.balanced.score.lib.interfaces.RewardsXCall; import network.balanced.score.lib.structs.PrepDelegations; -import network.balanced.score.lib.utils.Names; -import network.balanced.score.lib.utils.Versions; -import network.balanced.score.lib.utils.ArbitraryCallManager; +import network.balanced.score.lib.utils.*; import score.Address; import score.Context; import score.VarDB; @@ -39,7 +40,9 @@ import java.util.Map; import static network.balanced.score.core.governance.utils.GovernanceConstants.*; +import static network.balanced.score.lib.utils.BalancedAddressManager.getXCall; import static network.balanced.score.lib.utils.Check.*; +import static network.balanced.score.lib.utils.Check.checkStatus; import static network.balanced.score.lib.utils.Constants.MICRO_SECONDS_IN_A_DAY; public class GovernanceImpl implements Governance { @@ -55,6 +58,8 @@ public class GovernanceImpl implements Governance { public static final VarDB quorum = Context.newVarDB(QUORUM, BigInteger.class); private final VarDB currentVersion = Context.newVarDB(VERSION, String.class); + public static String NATIVE_NID; + public GovernanceImpl() { if (launched.getOrDefault(null) == null) { launched.set(false); @@ -168,7 +173,8 @@ public BigInteger getBalnVoteDefinitionCriterion() { public void defineVote(String name, String description, BigInteger vote_start, BigInteger duration, String forumLink, @Optional String transactions) { transactions = optionalDefault(transactions, "[]"); - ProposalManager.defineVote(name, description, vote_start, duration, forumLink, transactions); + String caller = new NetworkAddress(getNativeNid(), Context.getCaller()).toString(); + ProposalManager.defineVote(caller, name, description, vote_start, duration, forumLink, transactions); } @External @@ -196,7 +202,12 @@ public List getProposals(@Optional BigInteger batch_size, @Optional BigI @External public void castVote(BigInteger vote_index, boolean vote) { - ProposalManager.castVote(vote_index, vote); + NetworkAddress networkAddress = new NetworkAddress(getNativeNid(), Context.getCaller()); + ProposalManager.castVote(networkAddress, vote_index, vote); + } + + public void xCastVote(String from, BigInteger vote_index, boolean vote) { + ProposalManager.castVote(NetworkAddress.valueOf(from), vote_index, vote); } @External @@ -216,7 +227,14 @@ public Map checkVote(BigInteger _vote_index) { @External(readonly = true) public Map getVotesOfUser(BigInteger vote_index, Address user) { - return ProposalManager.getVotesOfUser(vote_index, user); + NetworkAddress networkAddress = new NetworkAddress(getNativeNid(), user); + return ProposalManager.getVotesOfUser(vote_index, networkAddress); + } + + @External(readonly = true) + public Map getVotesOfUserV2(BigInteger vote_index, String user) { + NetworkAddress networkAddress = NetworkAddress.valueOf(user, getNativeNid()); + return ProposalManager.getVotesOfUser(vote_index, networkAddress); } @External(readonly = true) @@ -226,7 +244,14 @@ public BigInteger totalBoostedBaln(BigInteger block) { @External(readonly = true) public BigInteger myVotingWeight(Address _address, BigInteger block) { - return ProposalManager.myVotingWeight(_address, block); + NetworkAddress networkAddress = new NetworkAddress(getNativeNid(), _address); + return ProposalManager.myVotingWeight(networkAddress.toString(), block); + } + + @External(readonly = true) + public BigInteger myVotingWeightV2(String _address, BigInteger block) { + NetworkAddress networkAddress = NetworkAddress.valueOf(_address, getNativeNid()); + return ProposalManager.myVotingWeight(networkAddress.toString(), block); } @External @@ -449,6 +474,14 @@ public void balwAdminTransfer(Address _from, Address _to, BigInteger _value, @Op Context.call(ContractManager.getAddress(Names.WORKERTOKEN), "adminTransfer", _from, _to, _value, _data); } + @External + public void handleCallMessage(String _from, byte[] _data, @Optional String[] _protocols) { + Check.checkStatus(); + only(BalancedAddressManager.getXCall()); + XCallUtils.verifyXCallProtocols(_from, _protocols); + GovernanceXCall.process(this, _from, _data); + } + @EventLog(indexed = 1) public void ContractUpdated(String name, String error) { @@ -523,4 +556,12 @@ private static Address getSystemScoreAddress() { rawAddress[0] = 1; return new Address(rawAddress); } + + public static String getNativeNid() { + if (NATIVE_NID == null) { + NATIVE_NID = Context.call(String.class, ContractManager.getAddress(Names.XCALL), "getNetworkId"); + } + + return NATIVE_NID; + } } diff --git a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalDB.java b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalDB.java index 4c5f914c5..e75f5e92e 100644 --- a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalDB.java +++ b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalDB.java @@ -16,6 +16,7 @@ package network.balanced.score.core.governance.proposal; +import network.balanced.score.lib.utils.NetworkAddressDictDB; import score.Address; import score.Context; import score.DictDB; @@ -39,8 +40,8 @@ public class ProposalDB { public final VarDB name; public final VarDB description; public final VarDB active; - public final DictDB forVotesOfUser; - public final DictDB againstVotesOfUser; + NetworkAddressDictDB forVotesOfUser; + NetworkAddressDictDB againstVotesOfUser; public final VarDB totalForVotes; public final VarDB forVotersCount; public final VarDB againstVotersCount; @@ -64,8 +65,8 @@ public ProposalDB(BigInteger varKey) { name = Context.newVarDB(key + "_name", String.class); description = Context.newVarDB(key + "_description", String.class); active = Context.newVarDB(key + "_active", Boolean.class); - forVotesOfUser = Context.newDictDB(key + "_for_votes_of_user", BigInteger.class); - againstVotesOfUser = Context.newDictDB(key + "_against_votes_of_user", BigInteger.class); + forVotesOfUser = new NetworkAddressDictDB<>(key + "_for_votes_of_user", BigInteger.class); + againstVotesOfUser = new NetworkAddressDictDB<>(key + "_against_votes_of_user", BigInteger.class); totalForVotes = Context.newVarDB(key + "_total_for_votes", BigInteger.class); forVotersCount = Context.newVarDB(key + "_for_voters_count", BigInteger.class); againstVotersCount = Context.newVarDB(key + "_against_voters_count", BigInteger.class); diff --git a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalManager.java b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalManager.java index 53ea398b6..6088d4fca 100644 --- a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalManager.java +++ b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/proposal/ProposalManager.java @@ -16,6 +16,7 @@ package network.balanced.score.core.governance.proposal; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.core.governance.utils.ContractManager; import network.balanced.score.lib.utils.ArbitraryCallManager; import network.balanced.score.lib.utils.Names; @@ -30,11 +31,12 @@ import static network.balanced.score.core.governance.GovernanceImpl.*; import static network.balanced.score.core.governance.utils.EventLogger.VoteCast; +import static network.balanced.score.core.governance.utils.EventLogger.VoteCastV2; import static network.balanced.score.core.governance.utils.GovernanceConstants.*; public class ProposalManager { - public static void defineVote(String name, String description, BigInteger vote_start, BigInteger duration, + public static void defineVote(String address, String name, String description, BigInteger vote_start, BigInteger duration, String forumLink, String transactions) { Context.require(description.length() <= 500, "Description must be less than or equal to 500 characters."); @@ -49,7 +51,7 @@ public static void defineVote(String name, String description, BigInteger vote_s Context.require(duration.compareTo(minVoteDuration.get()) >= 0, "Duration is below the minimum allowed " + "duration of " + minVoteDuration.get()); Context.require(voteIndex.equals(BigInteger.ZERO), "Poll name " + name + " has already been used."); - Context.require(checkBalnVoteCriterion(Context.getCaller(), snapshotBlock), + Context.require(checkBalnVoteCriterion(address, snapshotBlock), "User needs at least " + balnVoteDefinitionCriterion.get().divide(BigInteger.valueOf(100)) + "% of " + "total boosted baln supply to define a vote."); @@ -104,7 +106,7 @@ public static List getProposals(BigInteger batch_size, BigInteger offset return proposals; } - public static void castVote(BigInteger vote_index, boolean vote) { + public static void castVote(NetworkAddress networkAddress, BigInteger vote_index, boolean vote) { ProposalDB proposal = new ProposalDB(vote_index); Context.require((vote_index.compareTo(BigInteger.ZERO) > 0 && _getDay().compareTo(proposal.startDay.getOrDefault(BigInteger.ZERO)) >= 0 && @@ -112,15 +114,14 @@ public static void castVote(BigInteger vote_index, boolean vote) { proposal.active.getOrDefault(false), TAG + " :This is not an active poll."); - Address from = Context.getCaller(); BigInteger snapshot = proposal.snapshotBlock.get(); - BigInteger totalVote = myVotingWeight(from, snapshot); + BigInteger totalVote = myVotingWeight(networkAddress.toString(), snapshot); Context.require(!totalVote.equals(BigInteger.ZERO), TAG + "Boosted Balanced tokens needed to cast the vote."); - BigInteger userForVotes = proposal.forVotesOfUser.getOrDefault(from, BigInteger.ZERO); - BigInteger userAgainstVotes = proposal.againstVotesOfUser.getOrDefault(from, BigInteger.ZERO); + BigInteger userForVotes = proposal.forVotesOfUser.getOrDefault(networkAddress, BigInteger.ZERO); + BigInteger userAgainstVotes = proposal.againstVotesOfUser.getOrDefault(networkAddress, BigInteger.ZERO); BigInteger totalForVotes = proposal.totalForVotes.getOrDefault(BigInteger.ZERO); BigInteger totalAgainstVotes = proposal.totalAgainstVotes.getOrDefault(BigInteger.ZERO); BigInteger totalForVotersCount = proposal.forVotersCount.getOrDefault(BigInteger.ZERO); @@ -130,8 +131,8 @@ public static void castVote(BigInteger vote_index, boolean vote) { boolean isFirstTimeVote = userForVotes.signum() == 0 && userAgainstVotes.signum() == 0; if (vote) { - proposal.forVotesOfUser.set(from, totalVote); - proposal.againstVotesOfUser.set(from, BigInteger.ZERO); + proposal.forVotesOfUser.set(networkAddress, totalVote); + proposal.againstVotesOfUser.set(networkAddress, BigInteger.ZERO); //TODO use safemath totalFor = totalForVotes.add(totalVote).subtract(userForVotes); @@ -144,8 +145,8 @@ public static void castVote(BigInteger vote_index, boolean vote) { proposal.forVotersCount.set(totalForVotersCount.add(BigInteger.ONE)); } } else { - proposal.againstVotesOfUser.set(from, totalVote); - proposal.forVotesOfUser.set(from, BigInteger.ZERO); + proposal.againstVotesOfUser.set(networkAddress, totalVote); + proposal.forVotesOfUser.set(networkAddress, BigInteger.ZERO); //TODO use safemath totalFor = totalForVotes.subtract(userForVotes); totalAgainst = totalAgainstVotes.add(totalVote).subtract(userAgainstVotes); @@ -162,7 +163,7 @@ public static void castVote(BigInteger vote_index, boolean vote) { proposal.totalForVotes.set(totalFor); proposal.totalAgainstVotes.set(totalAgainst); - VoteCast(proposal.name.get(), vote, from, totalVote, totalFor, totalAgainst); + VoteCastV2(proposal.name.get(), vote, networkAddress.toString(), totalVote, totalFor, totalAgainst); } public static void evaluateVote(BigInteger vote_index) { @@ -263,7 +264,7 @@ public static Map getVotersCount(BigInteger vote_index) { ); } - public static Map getVotesOfUser(BigInteger vote_index, Address user) { + public static Map getVotesOfUser(BigInteger vote_index, NetworkAddress user) { ProposalDB proposal = new ProposalDB(vote_index); return Map.of( "for", proposal.forVotesOfUser.getOrDefault(user, BigInteger.ZERO), @@ -275,8 +276,8 @@ public static BigInteger totalBoostedBaln(BigInteger block) { return Context.call(BigInteger.class, ContractManager.getAddress(Names.BOOSTED_BALN), "totalSupplyAt", block); } - public static BigInteger myVotingWeight(Address _address, BigInteger block) { - return Context.call(BigInteger.class, ContractManager.getAddress(Names.BOOSTED_BALN), "balanceOfAt", _address + public static BigInteger myVotingWeight(String _address, BigInteger block) { + return Context.call(BigInteger.class, ContractManager.getAddress(Names.BOOSTED_BALN), "xBalanceOfAt", _address , block); } @@ -294,7 +295,7 @@ private static BigInteger totalBaln(BigInteger _day) { return call(BigInteger.class, ContractManager.getAddress(Names.BALN), "totalStakedBalanceOfAt", _day); } - private static boolean checkBalnVoteCriterion(Address address, BigInteger block) { + private static boolean checkBalnVoteCriterion(String address, BigInteger block) { BigInteger boostedBalnTotal = Context.call(BigInteger.class, ContractManager.getAddress(Names.BOOSTED_BALN), "totalSupplyAt", block); BigInteger userBoostedBaln = myVotingWeight(address, block); diff --git a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/utils/EventLogger.java b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/utils/EventLogger.java index a136f06b8..ec2ef45b2 100644 --- a/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/utils/EventLogger.java +++ b/core-contracts/Governance/src/main/java/network/balanced/score/core/governance/utils/EventLogger.java @@ -29,4 +29,12 @@ public static void VoteCast(String vote_name, boolean vote, Address voter, BigIn new Object[]{voter, stake, total_for, total_against} ); } + + public static void VoteCastV2(String vote_name, boolean vote, String voter, BigInteger stake, BigInteger total_for, + BigInteger total_against) { + Context.logEvent( + new Object[]{"VoteCast(str,bool,String,int,int,int)", vote_name, vote}, + new Object[]{voter, stake, total_for, total_against} + ); + } } diff --git a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTest.java b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTest.java index baf2369c4..8b4b403e7 100644 --- a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTest.java +++ b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTest.java @@ -19,6 +19,7 @@ import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; import com.iconloop.score.test.Account; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.structs.DistributionPercentage; import network.balanced.score.lib.structs.PrepDelegations; import network.balanced.score.lib.utils.Names; @@ -65,8 +66,8 @@ void getVotingWeight() { Account user = sm.createAccount(); BigInteger block = BigInteger.valueOf(Context.getBlockHeight()); BigInteger expectedWeight = BigInteger.ONE; - - when(bBaln.mock.balanceOfAt(user.getAddress(), block)).thenReturn(expectedWeight); + String networkAddress = NetworkAddress.valueOf(user.getAddress().toString(), NATIVE_NID).toString(); + when(bBaln.mock.xBalanceOfAt(networkAddress, block)).thenReturn(expectedWeight); // Act BigInteger votingWeight = (BigInteger) governance.call("myVotingWeight", user.getAddress(), block); diff --git a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTestBase.java b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTestBase.java index 82e071d1d..cdb681977 100644 --- a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTestBase.java +++ b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceTestBase.java @@ -21,6 +21,7 @@ import com.iconloop.score.test.Account; import com.iconloop.score.test.Score; import com.iconloop.score.test.ServiceManager; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.interfaces.*; import network.balanced.score.lib.test.UnitTest; import network.balanced.score.lib.test.mock.MockContract; @@ -45,6 +46,7 @@ public class GovernanceTestBase extends UnitTest { protected static final Account oracle = Account.newScoreAccount(scoreCount); + protected MockContract xCall; protected MockContract loans; protected MockContract dex; protected MockContract staking; @@ -65,6 +67,7 @@ public class GovernanceTestBase extends UnitTest { protected MockContract balancedOracle; protected Score governance; + public final String NATIVE_NID = "0x1.ICON"; protected JsonObject createJsonDistribution(String name, BigInteger dist) { return new JsonObject() @@ -141,6 +144,7 @@ private void setupAddresses() { governance.invoke(owner, "addExternalContract", Names.STABILITY, stability.getAddress()); governance.invoke(owner, "addExternalContract", Names.BALANCEDORACLE, balancedOracle.getAddress()); governance.invoke(owner, "addExternalContract", Names.BOOSTED_BALN, bBaln.getAddress()); + governance.invoke(owner, "addExternalContract", Names.XCALL, xCall.getAddress()); } protected BigInteger executeVoteWithActions(String actions) { @@ -153,7 +157,7 @@ protected BigInteger executeVoteWithActions(String actions) { String forumLink = "https://gov.balanced.network/"; when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(BigInteger.valueOf(20).multiply(ICX)); - when(bBaln.mock.balanceOfAt(eq(owner.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(ICX)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(owner.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(ICX)); governance.invoke(owner, "defineVote", name, description, voteStart, BigInteger.TWO, forumLink, actions); BigInteger id = (BigInteger) governance.call("getVoteIndex", name); @@ -181,8 +185,8 @@ protected BigInteger createVoteWith(String name, BigInteger totalSupply, BigInte Map vote = getVote(id); when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(totalSupply); - when(bBaln.mock.balanceOfAt(eq(forVoter.getAddress()), any(BigInteger.class))).thenReturn(forVotes); - when(bBaln.mock.balanceOfAt(eq(againstVoter.getAddress()), any(BigInteger.class))).thenReturn(againstVotes); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(forVoter.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(forVotes); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(againstVoter.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(againstVotes); goToDay((BigInteger) vote.get("start day")); @@ -207,7 +211,7 @@ protected BigInteger defineTestVoteWithName(String name) { String forumLink = "https://gov.balanced.network/"; when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(ICX)); - when(bBaln.mock.balanceOfAt(eq(owner.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.ONE.multiply(ICX)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(owner.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.ONE.multiply(ICX)); governance.invoke(owner, "defineVote", name, description, voteStart, BigInteger.TWO, forumLink, actions); @@ -229,6 +233,7 @@ protected void goToDay(BigInteger targetDay) { } protected void setup() throws Exception { + xCall = new MockContract<>(XCallScoreInterface.class, sm, owner); loans = new MockContract<>(LoansScoreInterface.class, sm, owner); dex = new MockContract<>(DexScoreInterface.class, sm, owner); staking = new MockContract<>(StakingScoreInterface.class, sm, owner); @@ -248,6 +253,8 @@ protected void setup() throws Exception { stability = new MockContract<>(StabilityScoreInterface.class, sm, owner); bBaln = new MockContract<>(BoostedBalnScoreInterface.class, sm, owner); balancedOracle = new MockContract<>(BalancedOracleScoreInterface.class, sm, owner); + + when(xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); governance = sm.deploy(owner, GovernanceImpl.class); setupAddresses(); diff --git a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceVotingTest.java b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceVotingTest.java index 1dcb47c43..38df346da 100644 --- a/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceVotingTest.java +++ b/core-contracts/Governance/src/test/java/network/balanced/score/core/governance/GovernanceVotingTest.java @@ -18,6 +18,7 @@ import com.eclipsesource.json.JsonArray; import com.iconloop.score.test.Account; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.core.governance.proposal.ProposalStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -54,8 +55,8 @@ void defineVote() { String actions = "[]"; String expectedErrorMessage; - when(bBaln.mock.balanceOfAt(eq(owner.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); - when(bBaln.mock.balanceOfAt(eq(accountWithLowBalance.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(owner.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(accountWithLowBalance.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(BigInteger.valueOf(6).multiply(EXA)); // Act & Assert @@ -126,7 +127,7 @@ void cancelVote_Owner() { String actions = "[]"; String expectedErrorMessage; - when(bBaln.mock.balanceOfAt(eq(proposer.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(proposer.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(BigInteger.valueOf(6).multiply(EXA)); governance.invoke(proposer, "defineVote", name, description, voteStart, voteDuration, forumLink, actions); @@ -180,7 +181,7 @@ void cancelVote_Proposer() { BigInteger voteDuration = BigInteger.TWO; String actions = "[]"; - when(bBaln.mock.balanceOfAt(eq(proposer.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(proposer.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.TEN.multiply(EXA)); when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(BigInteger.valueOf(6).multiply(EXA)); governance.invoke(proposer, "defineVote", name, description, voteStart, voteDuration, forumLink, actions); @@ -205,8 +206,8 @@ void castVote_restrictions() { String expectedErrorMessage; Map vote = getVote(id); - when(bBaln.mock.balanceOfAt(eq(owner.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.valueOf(8)); - when(bBaln.mock.balanceOfAt(eq(zeroBalanceAccount.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(owner.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.valueOf(8)); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(zeroBalanceAccount.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); // Act & Assert expectedErrorMessage = TAG + " :This is not an active poll."; @@ -264,11 +265,11 @@ void castVote() { Map vote = getVote(id); when(bBaln.mock.totalSupplyAt(any(BigInteger.class))).thenReturn(totalSupply); - when(bBaln.mock.balanceOfAt(eq(forVoter1.getAddress()), any(BigInteger.class))).thenReturn(forVoter1Balance); - when(bBaln.mock.balanceOfAt(eq(forVoter2.getAddress()), any(BigInteger.class))).thenReturn(forVoter2Balance); - when(bBaln.mock.balanceOfAt(eq(againstVoter.getAddress()), any(BigInteger.class))).thenReturn(againstVoterBalance); - when(bBaln.mock.balanceOfAt(eq(swayedAgainstVoter.getAddress()), any(BigInteger.class))).thenReturn(swayedAgainstVoterBalance); - when(bBaln.mock.balanceOfAt(eq(swayedForVoter.getAddress()), any(BigInteger.class))).thenReturn(swayedForVoterBalance); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(forVoter1.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(forVoter1Balance); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(forVoter2.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(forVoter2Balance); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(againstVoter.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(againstVoterBalance); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(swayedAgainstVoter.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(swayedAgainstVoterBalance); + when(bBaln.mock.xBalanceOfAt(eq(NetworkAddress.valueOf(swayedForVoter.getAddress().toString(), NATIVE_NID).toString()), any(BigInteger.class))).thenReturn(swayedForVoterBalance); goToDay((BigInteger) vote.get("start day")); diff --git a/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/RewardsImpl.java b/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/RewardsImpl.java index bba22a8ab..ac5477e61 100644 --- a/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/RewardsImpl.java +++ b/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/RewardsImpl.java @@ -162,6 +162,7 @@ public BigInteger getEmission(@Optional BigInteger _day) { public Map getBalnHoldings(String[] _holders) { Map holdings = new HashMap<>(); for (String address : _holders) { + address = NetworkAddress.valueOf(address, NATIVE_NID).toString(); holdings.put(address, balnHoldings.getOrDefault(address, BigInteger.ZERO)); } @@ -186,12 +187,14 @@ public Map getHoldings(String _holder) { @External(readonly = true) public BigInteger getBalnHolding(String _holder) { + _holder = NetworkAddress.valueOf(_holder, NATIVE_NID).toString(); Address baln = getBaln(); return getRewards(_holder).get(baln.toString()); } @External(readonly = true) public Map getRewards(String _holder) { + _holder = NetworkAddress.valueOf(_holder, NATIVE_NID).toString(); Map accruedRewards = getHoldings(_holder); int dataSourcesCount = DataSourceDB.size(); for (int i = 0; i < dataSourcesCount; i++) { @@ -248,6 +251,7 @@ public Map> getDataSources() { @External(readonly = true) public Map> getUserSourceData(String user) { + user = NetworkAddress.valueOf(user, NATIVE_NID).toString(); Map> dataSources = new HashMap<>(); int dataSourcesCount = DataSourceDB.size(); for (int i = 0; i < dataSourcesCount; i++) { @@ -302,6 +306,7 @@ public Map getSourceData(String _name) { @External(readonly = true) public Map getWorkingBalanceAndSupply(String _name, String _user) { DataSourceImpl datasource = DataSourceDB.get(_name); + _user = NetworkAddress.valueOf(_user, NATIVE_NID).toString(); return Map.of( "workingSupply", datasource.getWorkingSupply(true), "workingBalance", datasource.getWorkingBalance(_user, true) @@ -313,7 +318,7 @@ public Map> getBoostData(String user, @Optional if (sources == null) { sources = getAllSources(); } - + user = NetworkAddress.valueOf(user, NATIVE_NID).toString(); Map> boostData = new HashMap<>(); for (String name : sources) { Map sourceData = new HashMap<>(); @@ -382,11 +387,19 @@ private boolean mintAndAllocateBalnReward(BigInteger platformDay) { @External public void boost(String[] sources) { - checkStatus(); Address user = Context.getCaller(); + boostInternal(new NetworkAddress(NATIVE_NID, user).toString(), sources); + } + + public void xBoost(String from, String[] sources) { + boostInternal(from, sources); + } + + public void boostInternal(String user, String[] sources){ + checkStatus(); BigInteger boostedBalance = fetchBoostedBalance(user); BigInteger boostedSupply = fetchBoostedSupply(); - updateAllUserRewards(user.toString(), sources, boostedBalance, boostedSupply); + updateAllUserRewards(user, sources, boostedBalance, boostedSupply); } @External @@ -410,7 +423,8 @@ public void claimRewards(@Optional String[] sources) { if (sources == null || sources.length == 0) { sources = getAllSources(); } - _claimRewards(Context.getCaller().toString(), sources); + String networkAddress = NetworkAddress.valueOf(Context.getCaller().toString(), NATIVE_NID).toString(); + _claimRewards(networkAddress, sources); } private void _claimRewards(String address, String[] sources) { @@ -523,9 +537,9 @@ public void updateRewardsData(String _name, BigInteger _totalSupply, Address _us BigInteger currentTime = getTime(); distribute(); - String user = _user.toString(); + String user = new NetworkAddress(NATIVE_NID, _user).toString(); BalanceData balances = new BalanceData(); - balances.boostedBalance = fetchBoostedBalance(_user); + balances.boostedBalance = fetchBoostedBalance(user); balances.boostedSupply = fetchBoostedSupply(); Map balanceAndSupply = dataSource.loadCurrentSupply(user); balances.balance = balanceAndSupply.get(BALANCE); @@ -554,8 +568,8 @@ public void updateBatchRewardsData(String _name, BigInteger _totalSupply, Reward for (RewardsDataEntryOld entry : _data) { BalanceData balances = new BalanceData(); balances.boostedSupply = boostedSupply; - balances.boostedBalance = fetchBoostedBalance(entry._user); - String user = entry._user.toString(); + String user = new NetworkAddress(NATIVE_NID, entry._user).toString(); + balances.boostedBalance = fetchBoostedBalance(user); Map balanceAndSupply = dataSource.loadCurrentSupply(user); balances.balance = balanceAndSupply.get(BALANCE); balances.supply = balanceAndSupply.get(TOTAL_SUPPLY); @@ -577,6 +591,7 @@ public void updateBalanceAndSupply(String _name, BigInteger _totalSupply, String BigInteger currentTime = getTime(); distribute(); + _user = NetworkAddress.valueOf(_user, NATIVE_NID).toString(); BalanceData balances = new BalanceData(); balances.boostedBalance = fetchBoostedBalance(_user); @@ -619,27 +634,28 @@ public void updateBalanceAndSupplyBatch(String _name, BigInteger _totalSupply, R } @External - public void onKick(Address user) { + public void onKick(String user) { checkStatus(); only(getBoostedBaln()); BigInteger boostedSupply = fetchBoostedSupply(); - updateAllUserRewards(user.toString(), getAllSources(), BigInteger.ZERO, boostedSupply); + updateAllUserRewards(user, getAllSources(), BigInteger.ZERO, boostedSupply); } @External public void kick(Address user, String[] sources) { checkStatus(); - BigInteger boostedBalance = fetchBoostedBalance(user); + String networkAddress = new NetworkAddress(NATIVE_NID, user).toString(); + BigInteger boostedBalance = fetchBoostedBalance(networkAddress); BigInteger boostedSupply = fetchBoostedSupply(); - updateAllUserRewards(user.toString(), sources, boostedBalance, boostedSupply); + updateAllUserRewards(networkAddress, sources, boostedBalance, boostedSupply); } @External - public void onBalanceUpdate(Address user, BigInteger balance) { + public void onBalanceUpdate(String user, BigInteger balance) { checkStatus(); only(getBoostedBaln()); BigInteger boostedSupply = fetchBoostedSupply(); - updateAllUserRewards(user.toString(), getAllSources(), balance, boostedSupply); + updateAllUserRewards(user, getAllSources(), balance, boostedSupply); } @External @@ -658,6 +674,7 @@ public BigInteger getBoostWeight() { @External(readonly = true) public String[] getUserSources(String user) { + user = NetworkAddress.valueOf(user, NATIVE_NID).toString(); int dataSourcesCount = DataSourceDB.size(); List sources = new ArrayList<>(); for (int i = 0; i < dataSourcesCount; i++) { @@ -781,7 +798,12 @@ public BigInteger getRelativeSourceWeight(String name, @Optional BigInteger time @External public void voteForSource(String name, BigInteger userWeight) { checkStatus(); - SourceWeightController.voteForSourceWeights(name, userWeight); + SourceWeightController.voteForSourceWeights(new NetworkAddress(NATIVE_NID, Context.getCaller()).toString(), name, userWeight); + } + + public void xVoteForSource(String from, String name, BigInteger userWeight) { + checkStatus(); + SourceWeightController.voteForSourceWeights(from, name, userWeight); } @External(readonly = true) @@ -815,12 +837,26 @@ public Point getWeightsSumPerType(int typeId) { @External(readonly = true) public VotedSlope getUserSlope(Address user, String source) { - return SourceWeightController.getUserSlope(user, source); + NetworkAddress networkAddress = new NetworkAddress(NATIVE_NID, user); + return SourceWeightController.getUserSlope(networkAddress, source); + } + + @External(readonly = true) + public VotedSlope getUserSlopeV2(String user, String source) { + NetworkAddress networkAddress = NetworkAddress.valueOf(user, NATIVE_NID); + return SourceWeightController.getUserSlope(networkAddress, source); } @External(readonly = true) public BigInteger getLastUserVote(Address user, String source) { - return SourceWeightController.getLastUserVote(user, source); + NetworkAddress networkAddress = new NetworkAddress(NATIVE_NID, user); + return SourceWeightController.getLastUserVote(networkAddress, source); + } + + @External(readonly = true) + public BigInteger getLastUserVoteV2(String user, String source) { + NetworkAddress networkAddress = NetworkAddress.valueOf(user, NATIVE_NID); + return SourceWeightController.getLastUserVote(networkAddress, source); } @External(readonly = true) @@ -840,14 +876,25 @@ public int getSourceType(String sourceName) { @External(readonly = true) public Map> getUserVoteData(Address user) { + NetworkAddress networkAddress = new NetworkAddress(NATIVE_NID, user); + return getUserVoteDataInternal(networkAddress); + } + + @External(readonly = true) + public Map> getUserVoteDataV2(String user) { + NetworkAddress networkAddress = NetworkAddress.valueOf(user, NATIVE_NID); + return getUserVoteDataInternal(networkAddress); + } + + private Map> getUserVoteDataInternal(NetworkAddress networkAddress){ Map> data = new HashMap<>(); BigInteger currentTime = BigInteger.valueOf(Context.getBlockTimestamp()); int dataSourcesCount = DataSourceDB.size(); for (int i = 0; i < dataSourcesCount; i++) { String source = DataSourceDB.names.get(i); - VotedSlope votedSlope = getUserSlope(user, source); - BigInteger lastVote = SourceWeightController.getLastUserVote(user, source); + VotedSlope votedSlope = SourceWeightController.getUserSlope(networkAddress, source); + BigInteger lastVote = SourceWeightController.getLastUserVote(networkAddress, source); BigInteger timeSinceLastVote = currentTime.subtract(lastVote); if (timeSinceLastVote.compareTo(SourceWeightController.WEIGHT_VOTE_DELAY) > 0 && votedSlope.power.equals(BigInteger.ZERO)) { continue; @@ -1020,21 +1067,8 @@ private static BigInteger dailyDistribution(BigInteger day) { private BigInteger fetchBoostedBalance(String user) { NetworkAddress networkAddress = NetworkAddress.valueOf(user, NATIVE_NID); - Address address = null; try { - address = Address.fromString(user); - } catch (Exception ignored) { - } - if (!networkAddress.net().equals(NATIVE_NID) || address == null) { - return BigInteger.ZERO; - } - - return fetchBoostedBalance(address); - } - - private BigInteger fetchBoostedBalance(Address user) { - try { - return (BigInteger) RewardsImpl.call(getBoostedBaln(), "balanceOf", user, BigInteger.ZERO); + return (BigInteger) RewardsImpl.call(getBoostedBaln(), "xBalanceOf", networkAddress.toString(), BigInteger.ZERO); } catch (Exception e) { return BigInteger.ZERO; } @@ -1086,6 +1120,10 @@ public void NewTypeWeight(int typeId, BigInteger time, BigInteger weight, BigInt public void VoteForSource(String sourceName, Address user, BigInteger weight, BigInteger time) { } + @EventLog(indexed = 2) + public void VoteForSourceV2(String sourceName, String user, BigInteger weight, BigInteger time) { + } + @EventLog(indexed = 1) public void NewSource(String sourceName, int typeId, BigInteger weight) { } diff --git a/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/weight/SourceWeightController.java b/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/weight/SourceWeightController.java index fefb09d4e..b7d6284e5 100644 --- a/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/weight/SourceWeightController.java +++ b/core-contracts/Rewards/src/main/java/network/balanced/score/core/rewards/weight/SourceWeightController.java @@ -16,10 +16,14 @@ package network.balanced.score.core.rewards.weight; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.core.rewards.RewardsImpl; import network.balanced.score.lib.structs.Point; import network.balanced.score.lib.structs.VotedSlope; +import network.balanced.score.lib.utils.BranchedNetworkAddressArrayDB; import network.balanced.score.lib.utils.EnumerableSetDB; +import network.balanced.score.lib.utils.NetworkAddressBranchDictDB; +import network.balanced.score.lib.utils.NetworkAddressDictDB; import score.*; import java.math.BigInteger; @@ -47,15 +51,22 @@ public class SourceWeightController { private static final DictDB sourceTypes = Context.newDictDB("sourceTypes", Integer.class); private static final DictDB isVotable = Context.newDictDB("votable", Boolean.class); - private static final BranchDB> voteUserSlopes = Context.newBranchDB( - "voteUserSlopes", VotedSlope.class); +// private static final BranchDB> voteUserSlopes = Context.newBranchDB( +// "voteUserSlopes", VotedSlope.class); + private static final NetworkAddressBranchDictDB voteUserSlopes = new NetworkAddressBranchDictDB<>( + "voteUserSlopes", VotedSlope.class); - private static final DictDB voteUserPower = Context.newDictDB("voteUserPower", +// private static final DictDB voteUserPower = Context.newDictDB("voteUserPower", +// BigInteger.class); + private static final NetworkAddressDictDB voteUserPower = new NetworkAddressDictDB<>("voteUserPower", BigInteger.class); - private static final BranchDB> lastUserVote = Context.newBranchDB( +// private static final BranchDB> lastUserVote = Context.newBranchDB( +// "lastUserVote", BigInteger.class); + + private static final NetworkAddressBranchDictDB lastUserVote = new NetworkAddressBranchDictDB<>( "lastUserVote", BigInteger.class); - private static final BranchDB> activeUserWeights = Context.newBranchDB( + private static final BranchedNetworkAddressArrayDB activeUserWeights = new BranchedNetworkAddressArrayDB<>( "activeUserWeights", String.class); // Past and scheduled points for source weight, sum of weights per type, total weight @@ -394,14 +405,14 @@ public static void addType(String name, BigInteger weight) { * @param sourceName Source which `user` votes for * @param userWeight Weight for a source in bps (units of 0.01%). Minimal is 0.01%. Ignored if 0 */ - public static void voteForSourceWeights(String sourceName, BigInteger userWeight) { + public static void voteForSourceWeights(String user, String sourceName, BigInteger userWeight) { + NetworkAddress userNetworkAddress = NetworkAddress.valueOf(user); Context.require(isVotable.getOrDefault(sourceName, true) || userWeight.equals(BigInteger.ZERO), sourceName + " is not a votable source, you can only remove weight"); Address bBalnAddress = getBoostedBaln(); - Address user = Context.getCaller(); - BigInteger slope = Context.call(BigInteger.class, bBalnAddress, "getLastUserSlope", user); - BigInteger lockEnd = Context.call(BigInteger.class, bBalnAddress, "lockedEnd", user); + BigInteger slope = Context.call(BigInteger.class, bBalnAddress, "getLastUserSlopeV2", user); + BigInteger lockEnd = Context.call(BigInteger.class, bBalnAddress, "lockedEndV2", user); BigInteger timestamp = BigInteger.valueOf(Context.getBlockTimestamp()); BigInteger nextTime = getNextWeekTimestamp(); @@ -410,13 +421,13 @@ public static void voteForSourceWeights(String sourceName, BigInteger userWeight Context.require((userWeight.compareTo(BigInteger.ZERO) >= 0) && (userWeight.compareTo(VOTE_POINTS) <= 0), "Weight has to be between 0 and 10000"); BigInteger nextUserVote = - lastUserVote.at(user).getOrDefault(sourceName, BigInteger.ZERO).add(WEIGHT_VOTE_DELAY); + lastUserVote.getOrDefault(userNetworkAddress, sourceName, BigInteger.ZERO).add(WEIGHT_VOTE_DELAY); Context.require(timestamp.compareTo(nextUserVote) >= 0, "Cannot vote so often"); int sourceType = sourceTypes.get(sourceName) - 1; Context.require(sourceType >= 0, "Source not added"); // Prepare slopes and biases in memory - VotedSlope oldSlope = voteUserSlopes.at(user).getOrDefault(sourceName, new VotedSlope()); + VotedSlope oldSlope = voteUserSlopes.getOrDefault(userNetworkAddress, sourceName, new VotedSlope()); BigInteger oldDt = BigInteger.ZERO; if (oldSlope.end.compareTo(nextTime) > 0) { oldDt = oldSlope.end.subtract(nextTime); @@ -432,11 +443,11 @@ public static void voteForSourceWeights(String sourceName, BigInteger userWeight BigInteger newBias = newSlope.slope.multiply(newDt); // Check and update powers (weights) used - BigInteger powerUsed = voteUserPower.getOrDefault(user, BigInteger.ZERO); + BigInteger powerUsed = voteUserPower.getOrDefault(userNetworkAddress, BigInteger.ZERO); powerUsed = powerUsed.add(newSlope.power).subtract(oldSlope.power); Context.require((powerUsed.compareTo(BigInteger.ZERO) >= 0) && (powerUsed.compareTo(VOTE_POINTS) <= 0), "Used" + " too much power"); - voteUserPower.set(user, powerUsed); + voteUserPower.set(userNetworkAddress, powerUsed); // Remove old and schedule new slope changes // Remove slope changes for old slopes @@ -478,19 +489,19 @@ public static void voteForSourceWeights(String sourceName, BigInteger userWeight getTotal(); - voteUserSlopes.at(user).set(sourceName, newSlope); + voteUserSlopes.set( userNetworkAddress, sourceName, newSlope); // Record last action time if (userWeight.equals(BigInteger.ZERO)) { - removeFromArraydb(sourceName, activeUserWeights.at(user)); + removeFromArraydb(sourceName, activeUserWeights.at(userNetworkAddress, false)); } else { - if (!arrayDbContains(activeUserWeights.at(user), sourceName)) { - activeUserWeights.at(user).add(sourceName); + if (!arrayDbContains(activeUserWeights.at(userNetworkAddress, false), sourceName)) { + activeUserWeights.at(userNetworkAddress, false).add(sourceName); } } - lastUserVote.at(user).set(sourceName, timestamp); - rewards.VoteForSource(sourceName, user, newWeight, nextTime); + lastUserVote.set(userNetworkAddress, sourceName, timestamp); + rewards.VoteForSourceV2(sourceName, user, newWeight, nextTime); } public static void setVotable(String name, boolean votable) { @@ -546,12 +557,12 @@ public static Point getPointsSumPerType(int typeId) { return pointsSum.at(typeId).get(timeSum.get(typeId)); } - public static VotedSlope getUserSlope(Address user, String source) { - return voteUserSlopes.at(user).getOrDefault(source, new VotedSlope()); + public static VotedSlope getUserSlope(NetworkAddress user, String source) { + return voteUserSlopes.getOrDefault(user, source, new VotedSlope()); } - public static BigInteger getLastUserVote(Address user, String source) { - return lastUserVote.at(user).getOrDefault(source, BigInteger.ZERO); + public static BigInteger getLastUserVote(NetworkAddress user, String source) { + return lastUserVote.getOrDefault(user, source, BigInteger.ZERO); } diff --git a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestBase.java b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestBase.java index 45a72e50e..3c4e0b5bd 100644 --- a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestBase.java +++ b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestBase.java @@ -20,6 +20,7 @@ import com.iconloop.score.test.Account; import com.iconloop.score.test.Score; import com.iconloop.score.test.ServiceManager; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.interfaces.*; import network.balanced.score.lib.test.UnitTest; import network.balanced.score.lib.utils.Names; @@ -33,6 +34,7 @@ import score.Address; import score.Context; +import java.lang.annotation.Native; import java.math.BigInteger; import java.util.Map; @@ -113,13 +115,13 @@ void setup() throws Exception { ); when(loans.mock.getBalanceAndSupply(any(String.class), any(String.class))).thenReturn(emptyDataSource); when(dex.mock.getBalanceAndSupply(any(String.class), any(String.class))).thenReturn(emptyDataSource); - when(bBaln.mock.balanceOf(any(Address.class), any(BigInteger.class))).thenReturn(BigInteger.ZERO); + when(bBaln.mock.xBalanceOf(any(String.class), any(BigInteger.class))).thenReturn(BigInteger.ZERO); when(bBaln.mock.totalSupply(any(BigInteger.class))).thenReturn(BigInteger.ZERO); BigInteger currentTime = BigInteger.valueOf(sm.getBlock().getTimestamp()); BigInteger unlockTime = currentTime.add(MICRO_SECONDS_IN_A_DAY.multiply(BigInteger.valueOf(365))); - when(bBaln.mock.lockedEnd(any(Address.class))).thenReturn(unlockTime); + when(bBaln.mock.lockedEndV2(any(String.class))).thenReturn(unlockTime); sm.getBlock().increase(DAY); mockUserWeight(user, EXA); @@ -157,8 +159,8 @@ void mockBalanceAndSupply(MockContract dataSource, String "_balance", balance, "_totalSupply", supply ); - - when(dataSource.mock.getBalanceAndSupply(name, address.toString())).thenReturn(balanceAndSupply); + String addressNetworkAddress = new NetworkAddress(NATIVE_NID, address).toString(); + when(dataSource.mock.getBalanceAndSupply(name, addressNetworkAddress)).thenReturn(balanceAndSupply); } void mockBalanceAndSupply(MockContract dataSource, String name, String address, @@ -179,16 +181,18 @@ void verifyBalnReward(Address address, BigInteger expectedReward) { } BigInteger getOneDayRewards(Address address) { - BigInteger rewardsPre = (BigInteger) rewardsScore.call("getBalnHolding", address.toString()); + String networkAddress = new NetworkAddress(NATIVE_NID, address.toString()).toString(); + BigInteger rewardsPre = (BigInteger) rewardsScore.call("getBalnHolding", networkAddress); sm.getBlock().increase(DAY); rewardsScore.invoke(owner, "distribute"); - BigInteger rewardsPost = (BigInteger) rewardsScore.call("getBalnHolding", address.toString()); + BigInteger rewardsPost = (BigInteger) rewardsScore.call("getBalnHolding", networkAddress); return rewardsPost.subtract(rewardsPre); } Object getUserSources(Address address) { - return rewardsScore.call("getUserSources", address.toString()); + String networkAddress = new NetworkAddress(NATIVE_NID, address.toString()).toString(); + return rewardsScore.call("getUserSources", networkAddress); } void vote(Account user, String name, BigInteger weight) { @@ -196,7 +200,7 @@ void vote(Account user, String name, BigInteger weight) { } void mockUserWeight(Account user, BigInteger weight) { - when(bBaln.mock.getLastUserSlope(user.getAddress())).thenReturn(weight); + when(bBaln.mock.getLastUserSlopeV2(new NetworkAddress(NATIVE_NID, user.getAddress()).toString())).thenReturn(weight); } @SuppressWarnings("unchecked") diff --git a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestRewards.java b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestRewards.java index a333bb356..542e86406 100644 --- a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestRewards.java +++ b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/RewardsTestRewards.java @@ -17,6 +17,7 @@ package network.balanced.score.core.rewards; import com.iconloop.score.test.Account; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.structs.RewardsDataEntry; import network.balanced.score.lib.structs.RewardsDataEntryOld; import network.balanced.score.lib.utils.Names; @@ -151,6 +152,7 @@ void claimRewards_updateBalanceAndSupply() { void boostedRewards() { // Arrange Account account = sm.createAccount(); + String accountNetworkAddress = new NetworkAddress(NATIVE_NID, account.getAddress()).toString(); BigInteger loansBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger setupBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger initialSupply = BigInteger.valueOf(1_000_000).multiply(EXA); @@ -172,7 +174,7 @@ void boostedRewards() { assertEquals(unBoostedRewards.divide(EXA), userLoansDistribution.divide(EXA)); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "boost", getUserSources(account.getAddress())); @@ -191,6 +193,7 @@ void boostedRewards() { void boostedRewards_maxBoost() { // Arrange Account account = sm.createAccount(); + String accountNetworkAddress = new NetworkAddress(NATIVE_NID, account.getAddress()).toString(); BigInteger loansBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger initialSupply = BigInteger.valueOf(1_000_000).multiply(EXA); BigInteger currentSupply = initialSupply.add(loansBalance); @@ -198,7 +201,7 @@ void boostedRewards_maxBoost() { BigInteger bBalnBalance = loansBalance.multiply(bBalnSupply).divide(currentSupply); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(BigInteger.ZERO); mockBalanceAndSupply(loans, "Loans", account.getAddress(), loansBalance, currentSupply); rewardsScore.invoke(loans.account, "updateRewardsData", "Loans", initialSupply, account.getAddress(), @@ -213,7 +216,7 @@ void boostedRewards_maxBoost() { assertEquals(unBoostedRewards.divide(EXA), userLoansDistribution.divide(EXA)); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "boost", getUserSources(account.getAddress())); @@ -231,13 +234,14 @@ void boostedRewards_maxBoost() { void boostedRewards_updateBoostedBalance_claim() { // Arrange Account account = sm.createAccount(); + String accountNetworkAddress = new NetworkAddress(NATIVE_NID, account.getAddress()).toString(); BigInteger loansBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger loansTotalSupply = BigInteger.valueOf(1_000_000).multiply(EXA); BigInteger bBalnBalance = BigInteger.valueOf(177).multiply(EXA); BigInteger bBalnSupply = BigInteger.valueOf(500_000).multiply(EXA); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(BigInteger.ZERO); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(BigInteger.ZERO); mockBalanceAndSupply(loans, "Loans", account.getAddress(), loansBalance, loansTotalSupply); rewardsScore.invoke(loans.account, "updateRewardsData", "Loans", loansTotalSupply.subtract(loansBalance), @@ -252,7 +256,7 @@ void boostedRewards_updateBoostedBalance_claim() { assertEquals(unBoostedRewards.divide(EXA), userLoansDistribution.divide(EXA)); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "boost", getUserSources(account.getAddress())); @@ -268,7 +272,7 @@ void boostedRewards_updateBoostedBalance_claim() { // Act bBalnBalance = BigInteger.valueOf(250).multiply(EXA); bBalnSupply = BigInteger.valueOf(500_000).multiply(EXA); - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "claimRewards", getUserSources(account.getAddress())); @@ -285,6 +289,7 @@ void boostedRewards_updateBoostedBalance_claim() { void boostedRewards_updateBoostedBalance_onBalanceUpdate() { // Arrange Account account = sm.createAccount(); + String accountNetworkAddress = new NetworkAddress(NATIVE_NID, account.getAddress()).toString(); BigInteger loansBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger loansTotalSupply = BigInteger.valueOf(1_000_000).multiply(EXA); BigInteger bBalnBalance = BigInteger.valueOf(800).multiply(EXA); @@ -304,7 +309,7 @@ void boostedRewards_updateBoostedBalance_onBalanceUpdate() { assertEquals(unBoostedRewards.divide(EXA), userLoansDistribution.divide(EXA)); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "boost", getUserSources(account.getAddress())); @@ -318,8 +323,8 @@ void boostedRewards_updateBoostedBalance_onBalanceUpdate() { // Act bBalnBalance = BigInteger.valueOf(100).multiply(EXA); - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); - rewardsScore.invoke(bBaln.account, "onBalanceUpdate", account.getAddress(), bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); + rewardsScore.invoke(bBaln.account, "onBalanceUpdate", accountNetworkAddress, bBalnBalance); // Assert BigInteger boost = @@ -336,6 +341,7 @@ void boostedRewards_updateBoostedBalance_onBalanceUpdate() { void boostedRewards_updateRewardsData() { // Arrange Account account = sm.createAccount(); + String accountNetworkAddress = new NetworkAddress(NATIVE_NID, account.getAddress()).toString(); BigInteger loansBalance = BigInteger.valueOf(1000).multiply(EXA); BigInteger loansTotalSupply = BigInteger.valueOf(1_000_000).multiply(EXA); BigInteger bBalnBalance = BigInteger.valueOf(200).multiply(EXA); @@ -355,7 +361,7 @@ void boostedRewards_updateRewardsData() { assertEquals(unBoostedRewards.divide(EXA), userLoansDistribution.divide(EXA)); // Act - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); when(bBaln.mock.totalSupply(BigInteger.ZERO)).thenReturn(bBalnSupply); rewardsScore.invoke(account, "boost", getUserSources(account.getAddress())); @@ -371,7 +377,7 @@ void boostedRewards_updateRewardsData() { // Act bBalnBalance = BigInteger.valueOf(250).multiply(EXA); - when(bBaln.mock.balanceOf(eq(account.getAddress()), any(BigInteger.class))).thenReturn(bBalnBalance); + when(bBaln.mock.xBalanceOf(eq(accountNetworkAddress), any(BigInteger.class))).thenReturn(bBalnBalance); BigInteger newLoansBalance = BigInteger.valueOf(20000).multiply(EXA); BigInteger newLoansTotalSupply = loansTotalSupply.add(newLoansBalance).subtract(loansBalance); @@ -452,14 +458,14 @@ void claimRewards_updateBalanceAndSupplyBatch() { RewardsDataEntry user1Entry = new RewardsDataEntry(); user1Entry._balance =user1CurrentBalance; - user1Entry._user = account1.getAddress().toString(); + user1Entry._user = NetworkAddress.valueOf(account1.getAddress().toString(), NATIVE_NID).toString(); RewardsDataEntry user2Entry = new RewardsDataEntry(); user2Entry._balance = user2CurrentBalance; - user2Entry._user = account2.getAddress().toString(); + user2Entry._user = NetworkAddress.valueOf(account2.getAddress().toString(), NATIVE_NID).toString(); Object batch = new RewardsDataEntry[]{user1Entry, user2Entry}; rewardsScore.invoke(loans.account, "updateBalanceAndSupply", "Loans", initialTotalSupply, - supplyAccount.getAddress().toString(), initialTotalSupply); + NetworkAddress.valueOf(supplyAccount.getAddress().toString(), NATIVE_NID).toString(), initialTotalSupply); // Act rewardsScore.invoke(loans.account, "updateBalanceAndSupplyBatch", name, currentTotalSupply, batch); @@ -508,7 +514,7 @@ void getBalnHolding() { BigInteger startTimeInUS = BigInteger.valueOf(sm.getBlock().getTimestamp()); - BigInteger initialRewards = (BigInteger) rewardsScore.call("getBalnHolding", account.getAddress().toString()); + BigInteger initialRewards = (BigInteger) rewardsScore.call("getBalnHolding", NetworkAddress.valueOf(account.getAddress().toString(), NATIVE_NID).toString()); assertEquals(BigInteger.ZERO, initialRewards); sm.getBlock().increase(DAY*3); @@ -520,7 +526,7 @@ void getBalnHolding() { BigInteger loansDistribution = getVotePercentage("Loans").multiply(emission).divide(EXA); BigInteger userDistribution = loansDistribution.multiply(currentBalance).divide(currentTotalSupply); - BigInteger rewards = (BigInteger) rewardsScore.call("getBalnHolding", account.getAddress().toString()); + BigInteger rewards = (BigInteger) rewardsScore.call("getBalnHolding", NetworkAddress.valueOf(account.getAddress().toString(), NATIVE_NID).toString()); BigInteger diffInUS = timeInUS.subtract(startTimeInUS); BigInteger expectedRewards = userDistribution.multiply(diffInUS).divide(MICRO_SECONDS_IN_A_DAY); @@ -532,6 +538,7 @@ void getBalnHolding() { void getBalnHoldings() { // Arrange Account account = sm.createAccount(); + String addressNetworkAddress = NetworkAddress.valueOf(account.getAddress().toString(), NATIVE_NID).toString(); BigInteger initialBalance = BigInteger.ZERO.multiply(EXA); BigInteger initialSupply = BigInteger.TEN.multiply(EXA); @@ -559,10 +566,10 @@ void getBalnHoldings() { BigInteger timeDiffInUS = endTimeInUS.subtract(startTimeInUS); BigInteger expectedRewards = distribution.multiply(timeDiffInUS).divide(MICRO_SECONDS_IN_A_DAY); - Object users = new String[]{account.getAddress().toString()}; + Object users = new String[]{addressNetworkAddress}; Map rewards = (Map) rewardsScore.call("getBalnHoldings", users); - BigInteger reward = rewards.get(account.getAddress().toString()).divide(BigInteger.TEN); + BigInteger reward = rewards.get(addressNetworkAddress).divide(BigInteger.TEN); assertEquals(expectedRewards.divide(BigInteger.TEN), reward); } @@ -616,11 +623,11 @@ void getBalnHoldings_batch() { BigInteger user1ExpectedRewards = user1Distribution.multiply(timeDiffInUS).divide(MICRO_SECONDS_IN_A_DAY); BigInteger user2ExpectedRewards = user2Distribution.multiply(timeDiffInUS).divide(MICRO_SECONDS_IN_A_DAY); - Object users = new String[]{account1.getAddress().toString(), account2.getAddress().toString()}; + Object users = new String[]{NetworkAddress.valueOf(account1.getAddress().toString(), NATIVE_NID).toString(), NetworkAddress.valueOf(account2.getAddress().toString(), NATIVE_NID).toString()}; Map rewards = (Map) rewardsScore.call("getBalnHoldings", users); - BigInteger user1Rewards = rewards.get(account1.getAddress().toString()).divide(BigInteger.TEN); - BigInteger user2Rewards = rewards.get(account2.getAddress().toString()).divide(BigInteger.TEN); + BigInteger user1Rewards = rewards.get(NetworkAddress.valueOf(account1.getAddress().toString(), NATIVE_NID).toString()).divide(BigInteger.TEN); + BigInteger user2Rewards = rewards.get(NetworkAddress.valueOf(account2.getAddress().toString(), NATIVE_NID).toString()).divide(BigInteger.TEN); assertEquals(user1ExpectedRewards.divide(BigInteger.TEN), user1Rewards); assertEquals(user2ExpectedRewards.divide(BigInteger.TEN), user2Rewards); } diff --git a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/SourceWeightControllerTest.java b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/SourceWeightControllerTest.java index 9a4ea66d2..3d7e30034 100644 --- a/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/SourceWeightControllerTest.java +++ b/core-contracts/Rewards/src/test/java/network/balanced/score/core/rewards/SourceWeightControllerTest.java @@ -20,6 +20,7 @@ import com.iconloop.score.test.Account; import com.iconloop.score.test.Score; import com.iconloop.score.test.ServiceManager; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.core.rewards.weight.SourceWeightController; import network.balanced.score.lib.interfaces.BoostedBaln; import network.balanced.score.lib.test.UnitTest; @@ -60,6 +61,8 @@ public class SourceWeightControllerTest extends UnitTest { BigInteger unlockTime; + public final String NATIVE_NID = "0x1.ICON"; + @BeforeEach void setup() throws Exception { mockBalanced = new MockBalanced(sm, owner); @@ -82,7 +85,7 @@ void setup() throws Exception { BigInteger currentTime = BigInteger.valueOf(sm.getBlock().getTimestamp()); BigInteger unlockTime = currentTime.add(MICRO_SECONDS_IN_A_DAY.multiply(BigInteger.valueOf(365))); - when(bBaln.mock.lockedEnd(any(Address.class))).thenReturn(unlockTime); + when(bBaln.mock.lockedEndV2(any(String.class))).thenReturn(unlockTime); } @Test @@ -281,11 +284,11 @@ void getLastUserVote() { sm.getBlock().increase(); BigInteger timeAfterVote2 = BigInteger.valueOf(sm.getBlock().getTimestamp()); - + NetworkAddress userNetworkAddress = NetworkAddress.valueOf(user.getAddress().toString(), NATIVE_NID); // Assert - BigInteger lastUserVoteICX = (BigInteger) weightController.call("getLastUserVote", user.getAddress(), "sICX" + + BigInteger lastUserVoteICX = (BigInteger) weightController.call("getLastUserVote", userNetworkAddress, "sICX" + "/ICX"); - BigInteger lastUserVoteBnUSD = (BigInteger) weightController.call("getLastUserVote", user.getAddress(), "sICX" + + BigInteger lastUserVoteBnUSD = (BigInteger) weightController.call("getLastUserVote", userNetworkAddress, "sICX" + "/bnUSD"); assertTrue(lastUserVoteICX.compareTo(timeBeforeVote) > 0 && lastUserVoteICX.compareTo(timeAfterVote1) < 0); @@ -293,10 +296,10 @@ void getLastUserVote() { } private void vote(Account user, String name, BigInteger weight) { - weightController.invoke(user, "voteForSourceWeights", name, weight); + weightController.invoke(user, "voteForSourceWeights", new NetworkAddress(NATIVE_NID, user.getAddress()).toString(), name, weight); } private void mockUserWeight(Account user, BigInteger weight) { - when(bBaln.mock.getLastUserSlope(user.getAddress())).thenReturn(weight); + when(bBaln.mock.getLastUserSlopeV2(NetworkAddress.valueOf(user.getAddress().toString(), NATIVE_NID).toString())).thenReturn(weight); } } diff --git a/score-lib/build.gradle b/score-lib/build.gradle index 7950aa1e0..3a6f76941 100644 --- a/score-lib/build.gradle +++ b/score-lib/build.gradle @@ -33,6 +33,7 @@ dependencies { implementation Dependencies.javaeeScorex implementation Dependencies.minimalJson implementation 'xyz.venture23:xcall-lib:2.1.0' + implementation Dependencies.javaeeTokens compileOnly Dependencies.javaeeScoreClient annotationProcessor Dependencies.javaeeScoreClient diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/BoostedBaln.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/BoostedBaln.java index dcf35d1be..f27ef3875 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/BoostedBaln.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/BoostedBaln.java @@ -18,6 +18,7 @@ import foundation.icon.score.client.ScoreClient; import foundation.icon.score.client.ScoreInterface; +import network.balanced.score.lib.annotations.XCall; import network.balanced.score.lib.interfaces.addresses.AddressManager; import network.balanced.score.lib.interfaces.base.TokenFallback; import network.balanced.score.lib.interfaces.base.Version; @@ -48,7 +49,7 @@ public interface BoostedBaln extends AddressManager, TokenFallback, Version { BigInteger getTotalLocked(); @External(readonly = true) - List
getUsers(int start, int end); + List getUsers(int start, int end); @External(readonly = true) boolean hasLocked(Address _owner); @@ -56,18 +57,27 @@ public interface BoostedBaln extends AddressManager, TokenFallback, Version { @External(readonly = true) BigInteger getLastUserSlope(Address address); + @External(readonly = true) + BigInteger getLastUserSlopeV2(String address); + @External(readonly = true) BigInteger userPointHistoryTimestamp(Address address, BigInteger index); @External(readonly = true) BigInteger lockedEnd(Address address); + @External(readonly = true) + BigInteger lockedEndV2(String address); + @External void checkpoint(); @External void increaseUnlockTime(BigInteger unlockTime); + @XCall + void xIncreaseUnlockTime(String from, BigInteger unlockTime); + @External void kick(Address user); @@ -77,12 +87,30 @@ public interface BoostedBaln extends AddressManager, TokenFallback, Version { @External void withdrawEarly(); + @XCall + void xKick(String from); + + @XCall + void xWithdrawEarly(String from); + + @XCall + void xWithdraw(String from); + + @XCall + void checkpoint(String from); + @External(readonly = true) BigInteger balanceOf(Address _owner, @Optional BigInteger timestamp); + @External(readonly = true) + BigInteger xBalanceOf(String _owner, @Optional BigInteger timestamp); + @External(readonly = true) BigInteger balanceOfAt(Address _owner, BigInteger block); + @External(readonly = true) + BigInteger xBalanceOfAt(String _owner, BigInteger block); + @External(readonly = true) BigInteger totalSupply(@Optional BigInteger time); @@ -100,4 +128,7 @@ public interface BoostedBaln extends AddressManager, TokenFallback, Version { @External(readonly = true) BigInteger userPointEpoch(Address address); + + @External(readonly = true) + BigInteger xUserPointEpoch(String address); } diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Bribing.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Bribing.java index f38be238e..06e768d52 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Bribing.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Bribing.java @@ -18,10 +18,12 @@ import foundation.icon.score.client.ScoreClient; import foundation.icon.score.client.ScoreInterface; +import network.balanced.score.lib.annotations.XCall; import network.balanced.score.lib.interfaces.addresses.RewardsAddress; import network.balanced.score.lib.interfaces.base.Version; import score.Address; import score.annotation.External; +import score.annotation.Optional; import java.math.BigInteger; @@ -55,12 +57,21 @@ public interface Bribing extends RewardsAddress, Version { @External(readonly=true) BigInteger claimable(Address user, String source, Address bribeToken); + @External(readonly=true) + BigInteger xClaimable(String user, String source, Address bribeToken); + @External void updatePeriod(String source, Address bribeToken); @External void claimBribe(String source, Address bribeToken); + @External + void handleCallMessage(String _from, byte[] _data, @Optional String[] _protocols); + + @XCall + void xClaimTo(String from, String source, Address bribeToken); + @External void tokenFallback(Address _from, BigInteger _value, byte[] _data); } diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Dividends.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Dividends.java index 8609a540c..fe9170105 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Dividends.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Dividends.java @@ -18,6 +18,7 @@ import foundation.icon.score.client.ScoreClient; import foundation.icon.score.client.ScoreInterface; +import network.balanced.score.lib.annotations.XCall; import network.balanced.score.lib.interfaces.addresses.AddressManager; import network.balanced.score.lib.interfaces.base.Name; import network.balanced.score.lib.interfaces.base.TokenFallback; @@ -36,10 +37,10 @@ @ScoreInterface public interface Dividends extends Name, TokenFallback, AddressManager, Version { @External - void onBalanceUpdate(Address user, BigInteger bBalnBalance); + void onBalanceUpdate(String user, BigInteger bBalnBalance); @External - void onKick(Address user); + void onKick(String user); @External void setTimeOffset(BigInteger deltaTime); @@ -110,14 +111,20 @@ public interface Dividends extends Name, TokenFallback, AddressManager, Version @External void claimDividends(); + @XCall + void xClaimDividends(String from); + @External void claim(@Optional int _start, @Optional int _end); + @XCall + void xClaim(String from, @Optional Integer _start, @Optional Integer _end); + @External void accumulateDividends(Address user, @Optional int _start, @Optional int _end); - @External - void updateBalnStake(Address user, BigInteger prevStakedBalance, BigInteger currentTotalSupply); + @XCall + void xAccumulateDividends(String from, @Optional Integer _start, @Optional Integer _end); @External(readonly = true) Map getUserDividends(Address _account, @Optional int _start, @Optional int _end); diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Governance.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Governance.java index 1ea28d013..f5c5a1871 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Governance.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Governance.java @@ -17,6 +17,7 @@ import foundation.icon.score.client.ScoreClient; import foundation.icon.score.client.ScoreInterface; +import network.balanced.score.lib.annotations.XCall; import network.balanced.score.lib.interfaces.base.Fallback; import network.balanced.score.lib.interfaces.base.Name; import network.balanced.score.lib.interfaces.base.TokenFallback; @@ -161,6 +162,9 @@ void defineVote(String name, String description, BigInteger vote_start, BigInteg @External void castVote(BigInteger vote_index, boolean vote); + @XCall + void xCastVote(String from, BigInteger vote_index, boolean vote); + @External void evaluateVote(BigInteger vote_index); diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Rewards.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Rewards.java index 6cd9958f8..183f8f452 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/Rewards.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/Rewards.java @@ -82,6 +82,9 @@ public interface Rewards extends @External void boost(String[] sources); + @XCall + void xBoost(String from, String[] sources); + @External void claimRewards(@Optional String[] sources); @@ -113,13 +116,13 @@ public interface Rewards extends BigInteger getTimeOffset(); @External - void onKick(Address user); + void onKick(String user); @External void kick(Address user, String[] sources); @External - void onBalanceUpdate(Address user, BigInteger balance); + void onBalanceUpdate(String user, BigInteger balance); @External void setBoostWeight(BigInteger weight); diff --git a/score-lib/src/main/java/network/balanced/score/lib/interfaces/base/RewardsVoting.java b/score-lib/src/main/java/network/balanced/score/lib/interfaces/base/RewardsVoting.java index a670dc05d..d421aa2b8 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/interfaces/base/RewardsVoting.java +++ b/score-lib/src/main/java/network/balanced/score/lib/interfaces/base/RewardsVoting.java @@ -16,6 +16,7 @@ package network.balanced.score.lib.interfaces.base; +import network.balanced.score.lib.annotations.XCall; import score.Address; import score.annotation.External; import score.annotation.Optional; @@ -51,6 +52,9 @@ public interface RewardsVoting { @External void voteForSource(String name, BigInteger userWeight); + @XCall + void xVoteForSource(String from, String name, BigInteger userWeight); + @External(readonly = true) boolean isVotable(String name); @@ -63,6 +67,9 @@ public interface RewardsVoting { @External(readonly = true) BigInteger getLastUserVote(Address user, String source); + @External(readonly = true) + BigInteger getLastUserVoteV2(String user, String source); + @External(readonly = true) BigInteger getCurrentTypeWeight(int typeId); diff --git a/score-lib/src/main/java/network/balanced/score/lib/tokens/HubTokenImpl.java b/score-lib/src/main/java/network/balanced/score/lib/tokens/HubTokenImpl.java index 56ce4d3a4..4591f5aea 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/tokens/HubTokenImpl.java +++ b/score-lib/src/main/java/network/balanced/score/lib/tokens/HubTokenImpl.java @@ -17,6 +17,7 @@ package network.balanced.score.lib.tokens; import network.balanced.score.lib.interfaces.tokens.HubToken; +import network.balanced.score.lib.interfaces.tokens.HubTokenMessages; import network.balanced.score.lib.interfaces.tokens.HubTokenXCall; import network.balanced.score.lib.utils.BalancedAddressManager; import network.balanced.score.lib.utils.XCallUtils; @@ -28,7 +29,6 @@ import score.annotation.External; import score.annotation.Optional; import score.annotation.Payable; -import network.balanced.score.lib.interfaces.tokens.HubTokenMessages; import foundation.icon.xcall.NetworkAddress; import java.math.BigInteger; 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 index c2d097f23..dcb0828e7 100644 --- 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 @@ -9,8 +9,8 @@ public class AddressBranchDictDB { - private BranchDB> legacyAddressDictDB; - private BranchDB> addressDictDB; + private final BranchDB> legacyAddressDictDB; + private final BranchDB> addressDictDB; public AddressBranchDictDB(String id, Class valueClass) { this.legacyAddressDictDB = Context.newBranchDB(id, valueClass); diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/AddressEnumerableSet.java b/score-lib/src/main/java/network/balanced/score/lib/utils/AddressEnumerableSet.java new file mode 100644 index 000000000..04e96b57b --- /dev/null +++ b/score-lib/src/main/java/network/balanced/score/lib/utils/AddressEnumerableSet.java @@ -0,0 +1,63 @@ +package network.balanced.score.lib.utils; + +import com.iconloop.score.util.EnumerableSet; + +import foundation.icon.xcall.NetworkAddress; +import score.Address; + +public class AddressEnumerableSet { + + protected final EnumerableSet
legacyEnumerableSet; + protected final EnumerableSet enumerableSet; + + public AddressEnumerableSet(String id){ + legacyEnumerableSet = new EnumerableSet<>(id, Address.class); + enumerableSet = new EnumerableSet<>(id+"_migrated", String.class); + } + + public int length() { + return legacyEnumerableSet.length()+enumerableSet.length(); + } + + public String at(int index) { + if(index< legacyEnumerableSet.length()){ + return legacyEnumerableSet.at(index).toString(); + }else{ + index = index - enumerableSet.length(); + return enumerableSet.at(index); + } + } + + public boolean contains(String value) { + return enumerableSet.contains(value) || legacyEnumerableSet.contains(Address.fromString(NetworkAddress.valueOf(value).account())); + } + + //remove if not needed + public Integer indexOf(String value) { + Integer index = enumerableSet.indexOf(value); + Integer legacyIndex = legacyEnumerableSet.indexOf(Address.fromString(value)); //todo: check if throws error + if(index!=null){ + return index + legacyEnumerableSet.length(); + }else return legacyIndex; + } + + public void add(String value) { + if (!contains(value)) { + // add new value + enumerableSet.add(value); + } + } + + public void remove(String value) { + Integer index = enumerableSet.indexOf(value); + if(index!=null){ + enumerableSet.remove(value); + }else{ + Integer legacyIndex = legacyEnumerableSet.indexOf(Address.fromString(NetworkAddress.valueOf(value).account())); //todo: check if throws error + if(legacyIndex!=null){ + legacyEnumerableSet.remove(Address.fromString(value)); + } + } + } + +} diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/BalancedAddressManager.java b/score-lib/src/main/java/network/balanced/score/lib/utils/BalancedAddressManager.java index 6fa8a75c6..2f68ade9a 100644 --- a/score-lib/src/main/java/network/balanced/score/lib/utils/BalancedAddressManager.java +++ b/score-lib/src/main/java/network/balanced/score/lib/utils/BalancedAddressManager.java @@ -59,15 +59,6 @@ public static Address getAddress(String name) { return address; } - public static String getNativeNid() { - String nid = nativeNid.get(); - if (nid == null) { - nid = Context.call(String.class, getXCall(), "getNetworkId"); - } - - return nid; - } - public static Address getBaln() { return getAddress(Names.BALN); } diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/BranchedNetworkAddressArrayDB.java b/score-lib/src/main/java/network/balanced/score/lib/utils/BranchedNetworkAddressArrayDB.java new file mode 100644 index 000000000..ac9aba7e4 --- /dev/null +++ b/score-lib/src/main/java/network/balanced/score/lib/utils/BranchedNetworkAddressArrayDB.java @@ -0,0 +1,38 @@ +package network.balanced.score.lib.utils; + +import foundation.icon.xcall.NetworkAddress; +import score.*; + +public class BranchedNetworkAddressArrayDB { + private final BranchDB> legacyAddressDB; + private final BranchDB> addressDB; + + public BranchedNetworkAddressArrayDB(String id, Class valueClass) { + this.legacyAddressDB = Context.newBranchDB(id, valueClass); + this.addressDB = Context.newBranchDB(id + "_migrated", valueClass); + } + + public ArrayDB at(NetworkAddress user, boolean readOnly){ + ArrayDB value = addressDB.at(user.toString()); + if (value.size()>0) { + return value; + } + + if (user.account().startsWith("hx") || user.account().startsWith("cx")) { + value = legacyAddressDB.at(Address.fromString(user.account())); + if(!readOnly){ + int valueSize = value.size(); + for(int i=0; i { + + private final BranchDB> legacyAddressDictDB; + private final BranchDB> addressDictDB; + + public NetworkAddressBranchDictDB(String id, Class valueClass) { + this.legacyAddressDictDB = Context.newBranchDB(id, valueClass); + this.addressDictDB = Context.newBranchDB(id + "_migrated", valueClass); + } + + + public V get(NetworkAddress address, K id, boolean readOnly, @Optional V defaultValue) { + V value = addressDictDB.at(address.toString()).get(id); + if (value != null) { + return value; + } + + if (address.account().startsWith("hx") || address.account().startsWith("cx")) { + value = legacyAddressDictDB.at(Address.fromString(address.account())).get(id); + if(!readOnly){ + set(address, id, value); + } + } + + if(value==null){ + return defaultValue; + } + + return value; + } + + public V getOrDefault(NetworkAddress address, K id, V defaultValue) { + return get(address, id, true, defaultValue); + } + + + public void set(NetworkAddress address, K id, V value) { + addressDictDB.at(address.toString()).set(id, value); + } +} diff --git a/score-lib/src/main/java/network/balanced/score/lib/utils/NetworkAddressBranchedStringBranchDictDB.java b/score-lib/src/main/java/network/balanced/score/lib/utils/NetworkAddressBranchedStringBranchDictDB.java new file mode 100644 index 000000000..e98ebe923 --- /dev/null +++ b/score-lib/src/main/java/network/balanced/score/lib/utils/NetworkAddressBranchedStringBranchDictDB.java @@ -0,0 +1,48 @@ +package network.balanced.score.lib.utils; + +import foundation.icon.xcall.NetworkAddress; +import score.Address; +import score.BranchDB; +import score.Context; +import score.DictDB; +import score.annotation.Optional; + +public class NetworkAddressBranchedStringBranchDictDB { + private final BranchDB>> legacyAddressDictDB; + private final BranchDB>> addressDictDB; + + public NetworkAddressBranchedStringBranchDictDB(String id, Class valueClass) { + this.legacyAddressDictDB = Context.newBranchDB(id, valueClass); + this.addressDictDB = Context.newBranchDB(id + "_migrated", valueClass); + } + + + public V get(NetworkAddress address, K1 key1, K2 key2, boolean readOnly, @Optional V defaultValue) { + V value = addressDictDB.at(address.toString()).at(key1).get(key2); + if (value != null) { + return value; + } + + if (address.account().startsWith("hx") || address.account().startsWith("cx")) { + value = legacyAddressDictDB.at(Address.fromString(address.account())).at(key1).get(key2); + if(!readOnly){ + set(address, key1, key2, value); + } + } + + if(value==null){ + return defaultValue; + } + + return value; + } + + public V getOrDefault(NetworkAddress address, K1 key1, K2 key2, V defaultValue) { + return get(address, key1, key2, true, defaultValue); + } + + + public void set(NetworkAddress address, K1 key1, K2 key2, V value) { + addressDictDB.at(address.toString()).at(key1).set(key2, value); + } +} diff --git a/token-contracts/bBaln/build.gradle b/token-contracts/bBaln/build.gradle index fa721cf33..4b6f8bd56 100644 --- a/token-contracts/bBaln/build.gradle +++ b/token-contracts/bBaln/build.gradle @@ -27,10 +27,11 @@ repositories { dependencies { compileOnly Dependencies.javaeeApi - implementation project(':score-lib') implementation Dependencies.javaeeScorex implementation Dependencies.minimalJson implementation Dependencies.javaeeTokens + implementation project(':score-lib') + implementation 'xyz.venture23:xcall-lib:2.1.0' testImplementation Dependencies.javaeeUnitTest // Use JUnit Jupiter for testing. diff --git a/token-contracts/bBaln/src/intTest/java/network/balanced/score/tokens/BoostedBalnGeneralIntegrationTest.java b/token-contracts/bBaln/src/intTest/java/network/balanced/score/tokens/BoostedBalnGeneralIntegrationTest.java index 8dafdebdb..5c1fa59bc 100644 --- a/token-contracts/bBaln/src/intTest/java/network/balanced/score/tokens/BoostedBalnGeneralIntegrationTest.java +++ b/token-contracts/bBaln/src/intTest/java/network/balanced/score/tokens/BoostedBalnGeneralIntegrationTest.java @@ -117,7 +117,7 @@ void testCreateLockIncreaseTimeAndDeposit() { assertEquals(totalLocked.divide(EXA), availableBalnBalance.multiply(BigInteger.valueOf(3)).divide(BigInteger.valueOf(4)).divide(EXA)); - List
users = owner.boostedBaln.getUsers(0, 100); + List users = owner.boostedBaln.getUsers(0, 100); assert users.size() == 1; assertEquals(users.get(0), owner.getAddress()); diff --git a/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/AbstractBoostedBaln.java b/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/AbstractBoostedBaln.java index b7e2ff9c7..d334a20e0 100644 --- a/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/AbstractBoostedBaln.java +++ b/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/AbstractBoostedBaln.java @@ -15,10 +15,9 @@ */ package network.balanced.score.tokens; - -import com.iconloop.score.util.EnumerableSet; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.interfaces.BoostedBaln; -import network.balanced.score.lib.utils.Names; +import network.balanced.score.lib.utils.*; import network.balanced.score.tokens.db.LockedBalance; import network.balanced.score.tokens.db.Point; import network.balanced.score.tokens.utils.UnsignedBigInteger; @@ -44,7 +43,6 @@ public abstract class AbstractBoostedBaln implements BoostedBaln { public static BigInteger ICX = pow(BigInteger.TEN, 18); protected static final UnsignedBigInteger MULTIPLIER = pow10(18); - protected static final int DEPOSIT_FOR_TYPE = 0; protected static final int CREATE_LOCK_TYPE = 1; protected static final int INCREASE_LOCK_AMOUNT = 2; protected static final int INCREASE_UNLOCK_TIME = 3; @@ -56,26 +54,36 @@ public abstract class AbstractBoostedBaln implements BoostedBaln { protected final VarDB
penaltyAddress = Context.newVarDB("Boosted_baln_penalty_address", Address.class); - protected final DictDB locked = Context.newDictDB("Boosted_Baln_locked", - LockedBalance.class); +// protected final DictDB locked = Context.newDictDB("Boosted_Baln_locked", +// LockedBalance.class); + + protected static final AddressDictDB locked = new AddressDictDB<>("Boosted_Baln_locked", LockedBalance.class); + protected final VarDB epoch = Context.newVarDB("Boosted_Baln_epoch", BigInteger.class); protected final DictDB pointHistory = Context.newDictDB("Boosted_baln_point_history", Point.class); - protected final BranchDB> userPointHistory = Context.newBranchDB( - "Boosted_baln_user_point_history", Point.class); - protected final DictDB userPointEpoch = Context.newDictDB("Boosted_Baln_user_point_epoch", +// protected final BranchDB> userPointHistory = Context.newBranchDB( +// "Boosted_baln_user_point_history", Point.class); + protected final AddressBranchDictDB userPointHistory = new AddressBranchDictDB<>("Boosted_baln_user_point_history", Point.class); +// protected final DictDB userPointEpoch = Context.newDictDB("Boosted_Baln_user_point_epoch", +// BigInteger.class); + + protected final AddressDictDB userPointEpoch = new AddressDictDB<>("Boosted_Baln_user_point_epoch", BigInteger.class); protected final DictDB slopeChanges = Context.newDictDB("Boosted_Baln_slope_changes", BigInteger.class); - protected final EnumerableSet
users = new EnumerableSet<>("users_list", Address.class); + protected final AddressEnumerableSet users = new AddressEnumerableSet("users_list"); protected final VarDB minimumLockingAmount = Context.newVarDB("Boosted_baln_minimum_locking_amount", BigInteger.class); public final VarDB currentVersion = Context.newVarDB("version", String.class); + public static String NATIVE_NID; + public AbstractBoostedBaln(Address _governance, String name, String symbol) { onInstall(_governance, name, symbol); + NATIVE_NID = (String) Context.call(getXCall(), "getNetworkId"); } private void onInstall(Address _governance, String name, String symbol) { @@ -106,10 +114,18 @@ private void onInstall(Address _governance, String name, String symbol) { public void Deposit(Address provider, BigInteger locktime, BigInteger value, int type, BigInteger timestamp) { } + @EventLog(indexed = 2) + public void DepositV2(String provider, BigInteger locktime, BigInteger value, int type, BigInteger timestamp) { + } + @EventLog(indexed = 1) public void Withdraw(Address provider, BigInteger value, BigInteger timestamp) { } + @EventLog(indexed = 1) + public void WithdrawV2(String provider, BigInteger value, BigInteger timestamp) { + } + @EventLog public void Supply(BigInteger prevSupply, BigInteger supply) { } @@ -156,7 +172,7 @@ protected BigInteger findBlockEpoch(BigInteger block, BigInteger maxEpoch) { return min; } - protected BigInteger findUserPointHistory(Address address, BigInteger block) { + protected BigInteger findUserPointHistory(String address, BigInteger block) { BigInteger min = BigInteger.ZERO; BigInteger max = this.userPointEpoch.getOrDefault(address, BigInteger.ZERO); @@ -204,15 +220,20 @@ protected BigInteger supplyAt(Point point, BigInteger time) { return lastPoint.bias; } - protected LockedBalance getLockedBalance(Address user) { + protected LockedBalance getLockedBalance(String user) { return locked.getOrDefault(user, new LockedBalance()); } - protected Point getUserPointHistory(Address user, BigInteger epoch) { - return this.userPointHistory.at(user).getOrDefault(epoch, new Point()); + protected Point getUserPointHistory(String user, BigInteger epoch) { + user = user; + return this.userPointHistory.at(NetworkAddress.valueOf(user)).getOrDefault(epoch, new Point()); + } + + protected String getStringNetworkAddress(Address address){ + return new NetworkAddress(NATIVE_NID, address).toString(); } - protected void checkpoint(Address address, LockedBalance oldLocked, LockedBalance newLocked) { + protected void checkpoint(String address, LockedBalance oldLocked, LockedBalance newLocked) { Point uOld = new Point(); Point uNew = new Point(); BigInteger oldDSlope = BigInteger.ZERO; @@ -222,7 +243,7 @@ protected void checkpoint(Address address, LockedBalance oldLocked, LockedBalanc UnsignedBigInteger blockTimestamp = UnsignedBigInteger.valueOf(Context.getBlockTimestamp()); UnsignedBigInteger blockHeight = UnsignedBigInteger.valueOf(Context.getBlockHeight()); - if (!address.equals(EOA_ZERO)) { + if (!address.equals(getStringNetworkAddress(EOA_ZERO))) { // Calculate slopes and biases // Kept at zero when they have to if (oldLocked.end.compareTo(blockTimestamp) > 0 && oldLocked.amount.compareTo(BigInteger.ZERO) > 0) { @@ -310,7 +331,7 @@ protected void checkpoint(Address address, LockedBalance oldLocked, LockedBalanc } this.epoch.set(epoch); - if (!address.equals(EOA_ZERO)) { + if (!address.equals(getStringNetworkAddress(EOA_ZERO))) { lastPoint.slope = lastPoint.slope.add(uNew.slope.subtract(uOld.slope)); lastPoint.bias = lastPoint.bias.add(uNew.bias.subtract(uOld.bias)); @@ -324,7 +345,7 @@ protected void checkpoint(Address address, LockedBalance oldLocked, LockedBalanc this.pointHistory.set(epoch, lastPoint); - if (!address.equals(EOA_ZERO)) { + if (!address.equals(getStringNetworkAddress(EOA_ZERO))) { if (oldLocked.end.compareTo(blockTimestamp) > 0) { oldDSlope = oldDSlope.add(uOld.slope); if (newLocked.end.equals(oldLocked.end)) { @@ -343,34 +364,34 @@ protected void checkpoint(Address address, LockedBalance oldLocked, LockedBalanc this.userPointEpoch.set(address, userEpoch); uNew.timestamp = blockTimestamp; uNew.block = blockHeight; - this.userPointHistory.at(address).set(userEpoch, uNew); + this.userPointHistory.at(NetworkAddress.valueOf(address, NATIVE_NID)).set(userEpoch, uNew); } } - protected void depositFor(Address address, BigInteger value, BigInteger unlockTime, LockedBalance lockedBalance, + protected void depositFor(String address, BigInteger value, BigInteger unlockTime, LockedBalance lockedBalance, int type) { - LockedBalance locked = lockedBalance.newLockedBalance(); + LockedBalance balanceLocked = lockedBalance.newLockedBalance(); BigInteger supplyBefore = this.supply.get(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); this.supply.set(supplyBefore.add(value)); - LockedBalance oldLocked = locked.newLockedBalance(); + LockedBalance oldLocked = balanceLocked.newLockedBalance(); - locked.amount = locked.amount.add(value); + balanceLocked.amount = balanceLocked.amount.add(value); if (!unlockTime.equals(BigInteger.ZERO)) { - locked.end = new UnsignedBigInteger(unlockTime); + balanceLocked.end = new UnsignedBigInteger(unlockTime); } - this.locked.set(address, locked); - this.checkpoint(address, oldLocked, locked); + locked.set(address, balanceLocked); + this.checkpoint(address, oldLocked, balanceLocked); - Deposit(address, value, locked.getEnd(), type, blockTimestamp); + DepositV2(address, value, balanceLocked.getEnd(), type, blockTimestamp); Supply(supplyBefore, supplyBefore.add(value)); - onBalanceUpdate(address, balanceOf(address, blockTimestamp)); + onBalanceUpdate(address, xBalanceOf(address, blockTimestamp)); } - protected void createLock(Address sender, BigInteger value, BigInteger unlockTime) { + protected void createLock(String sender, BigInteger value, BigInteger unlockTime) { globalReentryLock(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); @@ -388,7 +409,7 @@ protected void createLock(Address sender, BigInteger value, BigInteger unlockTim this.depositFor(sender, value, unlockTime, locked, CREATE_LOCK_TYPE); } - protected void increaseAmount(Address sender, BigInteger value, BigInteger unlockTime) { + protected void increaseAmount(String sender, BigInteger value, BigInteger unlockTime) { globalReentryLock(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); LockedBalance locked = getLockedBalance(sender); @@ -408,7 +429,7 @@ protected void increaseAmount(Address sender, BigInteger value, BigInteger unloc this.depositFor(sender, value, unlockTime, locked, INCREASE_LOCK_AMOUNT); } - protected void onKick(Address user) { + protected void onKick(String user) { try { Context.call(getDividends(), "onKick", user); } catch (Exception ignored) { @@ -421,7 +442,7 @@ protected void onKick(Address user) { } - protected void onBalanceUpdate(Address user, BigInteger newBalance) { + protected void onBalanceUpdate(String user, BigInteger newBalance) { try { Context.call(getRewards(), "onBalanceUpdate", user, newBalance); } catch (Exception ignored) { diff --git a/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/BoostedBalnImpl.java b/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/BoostedBalnImpl.java index 1ccc50597..2d10c88dc 100644 --- a/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/BoostedBalnImpl.java +++ b/token-contracts/bBaln/src/main/java/network/balanced/score/tokens/BoostedBalnImpl.java @@ -18,9 +18,12 @@ import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; -import network.balanced.score.lib.utils.BalancedAddressManager; +import foundation.icon.xcall.NetworkAddress; +import network.balanced.score.lib.interfaces.BoostedBalnXCall; import network.balanced.score.lib.utils.Names; +import network.balanced.score.lib.utils.TokenTransfer; import network.balanced.score.lib.utils.Versions; +import network.balanced.score.lib.utils.XCallUtils; import network.balanced.score.tokens.db.LockedBalance; import network.balanced.score.tokens.db.Point; import network.balanced.score.tokens.utils.UnsignedBigInteger; @@ -35,9 +38,9 @@ import java.util.List; import java.util.Map; -import static network.balanced.score.lib.utils.Check.onlyOwner; -import static network.balanced.score.lib.utils.Check.checkStatus; import static network.balanced.score.lib.utils.BalancedAddressManager.getBaln; +import static network.balanced.score.lib.utils.BalancedAddressManager.getXCall; +import static network.balanced.score.lib.utils.Check.*; import static network.balanced.score.lib.utils.Constants.EOA_ZERO; import static network.balanced.score.lib.utils.Math.convertToNumber; import static network.balanced.score.lib.utils.NonReentrant.globalReentryLock; @@ -84,6 +87,12 @@ public Address getPenaltyAddress() { @External(readonly = true) public Map getLocked(Address _owner) { + LockedBalance balance = getLockedBalance(getStringNetworkAddress(_owner)); + return Map.of("amount", balance.amount, "end", balance.getEnd()); + } + + @External(readonly = true) + public Map getLockedV2(String _owner) { LockedBalance balance = getLockedBalance(_owner); return Map.of("amount", balance.amount, "end", balance.getEnd()); } @@ -94,10 +103,10 @@ public BigInteger getTotalLocked() { } @External(readonly = true) - public List
getUsers(int start, int end) { + public List getUsers(int start, int end) { Context.require(end - start <= 100, "Get users :Fetch only 100 users at a time"); - List
result = new ArrayList<>(); + List result = new ArrayList<>(); int _end = Math.min(end, users.length()); for (int index = start; index < _end; index++) { @@ -114,33 +123,60 @@ public int activeUsersCount() { @External(readonly = true) public boolean hasLocked(Address _owner) { + return users.contains(getStringNetworkAddress(_owner)); + } + + @External(readonly = true) + public boolean hasLockedV2(String _owner) { return users.contains(_owner); } @External(readonly = true) public BigInteger getLastUserSlope(Address address) { + String user = getStringNetworkAddress(address); + BigInteger userPointEpoch = this.userPointEpoch.get(user); + return getUserPointHistory(user, userPointEpoch).slope; + } + + @External(readonly = true) + public BigInteger getLastUserSlopeV2(String address) { BigInteger userPointEpoch = this.userPointEpoch.get(address); return getUserPointHistory(address, userPointEpoch).slope; } @External(readonly = true) public BigInteger userPointHistoryTimestamp(Address address, BigInteger index) { + return getUserPointHistory(getStringNetworkAddress(address), index).getTimestamp(); + } + + @External(readonly = true) + public BigInteger userPointHistoryTimestampV2(String address, BigInteger index) { return getUserPointHistory(address, index).getTimestamp(); } @External(readonly = true) public BigInteger lockedEnd(Address address) { + return getLockedBalance(getStringNetworkAddress(address)).getEnd(); + } + + @External(readonly = true) + public BigInteger lockedEndV2(String address) { return getLockedBalance(address).getEnd(); } @External public void checkpoint() { checkStatus(); - this.checkpoint(EOA_ZERO, new LockedBalance(), new LockedBalance()); + this.checkpoint(getStringNetworkAddress(EOA_ZERO), new LockedBalance(), new LockedBalance()); + } + + public void checkpoint(String from) { + checkStatus(); + this.checkpoint(getStringNetworkAddress(EOA_ZERO), new LockedBalance(), new LockedBalance()); } @External - public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { + public void xTokenFallback(String _from, BigInteger _value, byte[] _data) { checkStatus(); Address token = Context.getCaller(); Context.require(token.equals(getBaln()), "Token Fallback: Only Baln deposits are allowed"); @@ -169,14 +205,51 @@ public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { } } + @External + public void tokenFallback(Address _from, BigInteger _value, byte[] _data) { + checkStatus(); + Address token = Context.getCaller(); + Context.require(token.equals(getBaln()), "Token Fallback: Only Baln deposits are allowed"); + Context.require(_value.signum() > 0, "Token Fallback: Token value should be a positive number"); + + String unpackedData = new String(_data); + Context.require(!unpackedData.isEmpty(), "Token Fallback: Data can't be empty"); + + JsonObject json = Json.parse(unpackedData).asObject(); + String method = json.get("method").asString(); + JsonObject params = json.get("params").asObject(); + BigInteger unlockTime = convertToNumber(params.get("unlockTime"), BigInteger.ZERO); + String stringFrom = getStringNetworkAddress(_from); + switch (method) { + case "increaseAmount": + this.increaseAmount(stringFrom, _value, unlockTime); + break; + case "createLock": + BigInteger minimumLockingAmount = this.minimumLockingAmount.get(); + Context.require(_value.compareTo(minimumLockingAmount) >= 0, "insufficient locking amount. minimum " + + "amount is: " + minimumLockingAmount); + this.createLock(stringFrom, _value, unlockTime); + break; + default: + throw new UserRevertedException("Token fallback: Unimplemented token fallback action"); + } + } + @External public void increaseUnlockTime(BigInteger unlockTime) { + increaseUnlockTimeInternal(getStringNetworkAddress(Context.getCaller()), unlockTime); + } + + public void xIncreaseUnlockTime(String from, BigInteger unlockTime){ + increaseUnlockTimeInternal(from, unlockTime); + } + + private void increaseUnlockTimeInternal(String stingSender, BigInteger unlockTime){ checkStatus(); globalReentryLock(); - Address sender = Context.getCaller(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); - LockedBalance locked = getLockedBalance(sender); + LockedBalance locked = getLockedBalance(stingSender); unlockTime = unlockTime.divide(WEEK_IN_MICRO_SECONDS).multiply(WEEK_IN_MICRO_SECONDS); Context.require(locked.amount.compareTo(BigInteger.ZERO) > 0, "Increase unlock time: Nothing is locked"); @@ -186,87 +259,141 @@ public void increaseUnlockTime(BigInteger unlockTime) { Context.require(unlockTime.compareTo(blockTimestamp.add(MAX_TIME)) <= 0, "Increase unlock time: Voting lock " + "can be 4 years max"); - this.depositFor(sender, BigInteger.ZERO, unlockTime, locked, INCREASE_UNLOCK_TIME); + this.depositFor(stingSender, BigInteger.ZERO, unlockTime, locked, INCREASE_UNLOCK_TIME); } @External public void kick(Address user) { + kickInternal(getStringNetworkAddress(user)); + } + + public void xKick(String from){ + kickInternal(from); + } + + private void kickInternal(String stringUser){ checkStatus(); - BigInteger bBalnBalance = balanceOf(user, BigInteger.ZERO); + BigInteger bBalnBalance = xBalanceOf(stringUser, BigInteger.ZERO); if (bBalnBalance.equals(BigInteger.ZERO)) { - onKick(user); + onKick(stringUser); } else { - onBalanceUpdate(user, bBalnBalance); + onBalanceUpdate(stringUser, bBalnBalance); } } @External public void withdraw() { + withdrawInternal(getStringNetworkAddress(Context.getCaller())); + } + + + private void withdrawInternal(String senderAddress){ checkStatus(); globalReentryLock(); - Address sender = Context.getCaller(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); + LockedBalance balanceLocked = getLockedBalance(senderAddress); + Context.require(blockTimestamp.compareTo(balanceLocked.getEnd()) >= 0, "Withdraw: The lock haven't expire"); + BigInteger value = balanceLocked.amount; - LockedBalance locked = getLockedBalance(sender); - Context.require(blockTimestamp.compareTo(locked.getEnd()) >= 0, "Withdraw: The lock haven't expire"); - BigInteger value = locked.amount; + LockedBalance oldLocked = balanceLocked.newLockedBalance(); + balanceLocked.end = UnsignedBigInteger.ZERO; + balanceLocked.amount = BigInteger.ZERO; - LockedBalance oldLocked = locked.newLockedBalance(); - locked.end = UnsignedBigInteger.ZERO; - locked.amount = BigInteger.ZERO; - - this.locked.set(sender, locked); + locked.set(senderAddress, balanceLocked); BigInteger supplyBefore = this.supply.get(); this.supply.set(supplyBefore.subtract(value)); - this.checkpoint(sender, oldLocked, locked); + this.checkpoint(senderAddress, oldLocked, balanceLocked); - Context.call(getBaln(), "transfer", sender, value, "withdraw".getBytes()); + TokenTransfer.transfer(getBaln(), senderAddress, value, "withdraw".getBytes()); - users.remove(sender); - Withdraw(sender, value, blockTimestamp); + users.remove(senderAddress); + WithdrawV2(senderAddress, value, blockTimestamp); Supply(supplyBefore, supplyBefore.subtract(value)); - onKick(sender); + onKick(senderAddress); + } + + @External + public void handleCallMessage(String _from, byte[] _data, @Optional String[] _protocols) { + checkStatus(); + only(getXCall()); + XCallUtils.verifyXCallProtocols(_from, _protocols); + BoostedBalnXCall.process(this, _from, _data); + } + + public void xWithdrawEarly(String _from) { + withdrawEarlyInternal(_from); + } + + public void xWithdraw(String _from) { + withdrawInternal(_from); } @External public void withdrawEarly() { + withdrawEarlyInternal(getStringNetworkAddress(Context.getCaller())); + } + + private void withdrawEarlyInternal(String senderAddress){ checkStatus(); globalReentryLock(); Address sender = Context.getCaller(); BigInteger blockTimestamp = BigInteger.valueOf(Context.getBlockTimestamp()); - LockedBalance locked = getLockedBalance(sender); - Context.require(blockTimestamp.compareTo(locked.getEnd()) < 0, "Withdraw: The lock has expired, use withdraw " + + LockedBalance lockedBalance = getLockedBalance(senderAddress); + Context.require(blockTimestamp.compareTo(lockedBalance.getEnd()) < 0, "Withdraw: The lock has expired, use withdraw " + "method"); - BigInteger value = locked.amount; + BigInteger value = lockedBalance.amount; BigInteger maxPenalty = value.divide(BigInteger.TWO); BigInteger variablePenalty = balanceOf(sender, null); BigInteger penaltyAmount = variablePenalty.min(maxPenalty); BigInteger returnAmount = value.subtract(penaltyAmount); - LockedBalance oldLocked = locked.newLockedBalance(); - locked.end = UnsignedBigInteger.ZERO; - locked.amount = BigInteger.ZERO; - this.locked.set(sender, locked); + LockedBalance oldLocked = lockedBalance.newLockedBalance(); + lockedBalance.end = UnsignedBigInteger.ZERO; + lockedBalance.amount = BigInteger.ZERO; + locked.set(senderAddress, lockedBalance); BigInteger supplyBefore = this.supply.get(); this.supply.set(supplyBefore.subtract(value)); - this.checkpoint(sender, oldLocked, locked); + this.checkpoint(senderAddress, oldLocked, lockedBalance); Context.call(getBaln(), "transfer", this.penaltyAddress.get(), penaltyAmount, "withdrawPenalty".getBytes()); - Context.call(getBaln(), "transfer", sender, returnAmount, "withdrawEarly".getBytes()); + TokenTransfer.transfer(getBaln(), senderAddress, returnAmount, "withdrawEarly".getBytes()); - users.remove(sender); + users.remove(senderAddress); Withdraw(sender, value, blockTimestamp); Supply(supplyBefore, supplyBefore.subtract(value)); - onKick(sender); + onKick(senderAddress); } @External(readonly = true) public BigInteger balanceOf(Address _owner, @Optional BigInteger timestamp) { + UnsignedBigInteger uTimestamp; + String ownerAddress = getStringNetworkAddress(_owner); + if (timestamp == null || timestamp.equals(BigInteger.ZERO)) { + uTimestamp = UnsignedBigInteger.valueOf(Context.getBlockTimestamp()); + } else { + uTimestamp = new UnsignedBigInteger(timestamp); + } + + BigInteger epoch = this.userPointEpoch.getOrDefault(ownerAddress, BigInteger.ZERO); + if (epoch.equals(BigInteger.ZERO)) { + return BigInteger.ZERO; + } else { + Point lastPoint = getUserPointHistory(ownerAddress, epoch); + UnsignedBigInteger _delta = uTimestamp.subtract(lastPoint.timestamp); + return lastPoint.bias + .subtract(lastPoint.slope.multiply(_delta.toBigInteger())) + .max(BigInteger.ZERO); + + } + } + + @External(readonly = true) + public BigInteger xBalanceOf(String _owner, @Optional BigInteger timestamp) { UnsignedBigInteger uTimestamp; if (timestamp == null || timestamp.equals(BigInteger.ZERO)) { uTimestamp = UnsignedBigInteger.valueOf(Context.getBlockTimestamp()); @@ -280,22 +407,22 @@ public BigInteger balanceOf(Address _owner, @Optional BigInteger timestamp) { } else { Point lastPoint = getUserPointHistory(_owner, epoch); UnsignedBigInteger _delta = uTimestamp.subtract(lastPoint.timestamp); - BigInteger balance = lastPoint.bias + return lastPoint.bias .subtract(lastPoint.slope.multiply(_delta.toBigInteger())) .max(BigInteger.ZERO); - return balance; } } @External(readonly = true) public BigInteger balanceOfAt(Address _owner, BigInteger block) { + String ownerAddress = getStringNetworkAddress(_owner); UnsignedBigInteger blockHeight = UnsignedBigInteger.valueOf(Context.getBlockHeight()); UnsignedBigInteger blockTimestamp = UnsignedBigInteger.valueOf(Context.getBlockTimestamp()); Context.require(block.compareTo(blockHeight.toBigInteger()) <= 0, "BalanceOfAt: Invalid given block height"); - BigInteger userEpoch = this.findUserPointHistory(_owner, block); - Point uPoint = this.userPointHistory.at(_owner).getOrDefault(userEpoch, new Point()); + BigInteger userEpoch = this.findUserPointHistory(ownerAddress, block); + Point uPoint = this.userPointHistory.at(NetworkAddress.valueOf (ownerAddress) ).getOrDefault(userEpoch, new Point()); BigInteger maxEpoch = this.epoch.get(); BigInteger epoch = this.findBlockEpoch(block, maxEpoch); @@ -319,9 +446,42 @@ public BigInteger balanceOfAt(Address _owner, BigInteger block) { } UnsignedBigInteger delta = blockTime.subtract(uPoint.timestamp); - BigInteger balance = uPoint.bias.subtract(uPoint.slope.multiply(delta.toBigInteger())).max(BigInteger.ZERO); + return uPoint.bias.subtract(uPoint.slope.multiply(delta.toBigInteger())).max(BigInteger.ZERO); + + } + + @External(readonly = true) + public BigInteger xBalanceOfAt(String _owner, BigInteger block) { + UnsignedBigInteger blockHeight = UnsignedBigInteger.valueOf(Context.getBlockHeight()); + UnsignedBigInteger blockTimestamp = UnsignedBigInteger.valueOf(Context.getBlockTimestamp()); + + Context.require(block.compareTo(blockHeight.toBigInteger()) <= 0, "BalanceOfAt: Invalid given block height"); + BigInteger userEpoch = this.findUserPointHistory(_owner, block); + Point uPoint = this.userPointHistory.at(NetworkAddress.valueOf(_owner, NATIVE_NID) ).getOrDefault(userEpoch, new Point()); + + BigInteger maxEpoch = this.epoch.get(); + BigInteger epoch = this.findBlockEpoch(block, maxEpoch); + Point point0 = this.pointHistory.getOrDefault(epoch, new Point()); + UnsignedBigInteger dBlock; + UnsignedBigInteger dTime; - return balance; + if (epoch.compareTo(maxEpoch) < 0) { + Point point1 = this.pointHistory.getOrDefault(epoch.add(BigInteger.ONE), new Point()); + dBlock = point1.block.subtract(point0.block); + dTime = point1.timestamp.subtract(point0.timestamp); + } else { + dBlock = blockHeight.subtract(point0.block); + dTime = blockTimestamp.subtract(point0.timestamp); + } + + UnsignedBigInteger blockTime = point0.timestamp; + if (!dBlock.equals(UnsignedBigInteger.ZERO)) { + blockTime = blockTime.add(dTime.multiply(new UnsignedBigInteger(block).subtract(point0.block)) + .divide(dBlock)); + } + + UnsignedBigInteger delta = blockTime.subtract(uPoint.timestamp); + return uPoint.bias.subtract(uPoint.slope.multiply(delta.toBigInteger())).max(BigInteger.ZERO); } @External(readonly = true) @@ -367,6 +527,12 @@ public BigInteger totalSupplyAt(BigInteger block) { @External(readonly = true) public BigInteger userPointEpoch(Address address) { + String userAddress = getStringNetworkAddress(address); + return this.userPointEpoch.getOrDefault(userAddress, BigInteger.ZERO); + } + + @External(readonly = true) + public BigInteger xUserPointEpoch(String address) { return this.userPointEpoch.getOrDefault(address, BigInteger.ZERO); } } diff --git a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBALNUnlockTest.java b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBALNUnlockTest.java index 50aeb2bd4..d0c287740 100644 --- a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBALNUnlockTest.java +++ b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBALNUnlockTest.java @@ -19,6 +19,7 @@ import com.iconloop.score.test.Score; import com.iconloop.score.test.ServiceManager; +import foundation.icon.xcall.NetworkAddress; import network.balanced.score.lib.test.mock.MockBalanced; import network.balanced.score.lib.utils.BalancedAddressManager; import network.balanced.score.tokens.utils.DummyContract; @@ -50,6 +51,8 @@ public class BoostedBALNUnlockTest extends AbstractBoostedBalnTest { private BoostedBalnImpl scoreSpy; + private static final String NATIVE_NID = "0x1.ICON"; + public static BigInteger WEEK = BigInteger.TEN.pow(6).multiply(BigInteger.valueOf(86400L).multiply(BigInteger.valueOf(7L))); private static final BigInteger INITIAL_SUPPLY = BigInteger.TEN.multiply(ICX); @@ -59,6 +62,7 @@ public class BoostedBALNUnlockTest extends AbstractBoostedBalnTest { @BeforeEach public void setup() throws Exception { MockBalanced mockBalanced = new MockBalanced(sm, owner); + when(mockBalanced.xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); MockBalanced.addressManagerMock.when(() -> BalancedAddressManager.getBaln()).thenReturn(tokenScore.getAddress()); bBALNScore = sm.deploy(owner, BoostedBalnImpl.class, mockBalanced.governance.getAddress(), B_BALANCED_SYMBOL); @@ -153,20 +157,20 @@ public void testKick() { doNothing().when(scoreSpy).onKick(any()); tokenScore.invoke(owner, "transfer", bBALNScore.getAddress(), ICX.multiply(BigInteger.ONE), lockBytes); - Map balance = (Map) bBALNScore.call("getLocked", owner.getAddress()); + //Map balance = (Map) bBALNScore.call("getLocked", owner.getAddress()); BigInteger halfTime = BigInteger.valueOf(unlockTime).divide(MICRO_SECONDS_IN_A_SECOND).divide(BigInteger.valueOf(4)); sm.getBlock().increase(halfTime.longValue()); bBALNScore.invoke(owner, "kick", owner.getAddress()); - - verify(scoreSpy, times(2)).onBalanceUpdate(eq(owner.getAddress()), any(BigInteger.class)); + String stringOwner = new NetworkAddress(NATIVE_NID, owner.getAddress()).toString(); + verify(scoreSpy, times(2)).onBalanceUpdate(eq(stringOwner), any(BigInteger.class)); sm.getBlock().increase(halfTime.longValue()); bBALNScore.invoke(owner, "kick", owner.getAddress()); - verify(scoreSpy).onKick(owner.getAddress()); + verify(scoreSpy).onKick(stringOwner); } private static Stream weekListLock() { diff --git a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBalnTest.java b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBalnTest.java index 1658ab5be..49b0821a3 100644 --- a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBalnTest.java +++ b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/BoostedBalnTest.java @@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; class BoostedBalnTest extends AbstractBoostedBalnTest { private static final ServiceManager sm = getServiceManager(); @@ -44,6 +45,7 @@ class BoostedBalnTest extends AbstractBoostedBalnTest { private static final String bBalnName = "Boosted Balance"; private static final String bBalnSymbol = "bBALN"; + private static final String NATIVE_NID = "0x1.ICON"; public static class IRC2BasicToken extends IRC2Basic { public IRC2BasicToken(String _name, String _symbol, int _decimals, BigInteger _totalSupply) { @@ -55,6 +57,7 @@ public IRC2BasicToken(String _name, String _symbol, int _decimals, BigInteger _t @BeforeEach public void setup() throws Exception { MockBalanced mockBalanced = new MockBalanced(sm, owner); + when(mockBalanced.xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); MockBalanced.addressManagerMock.when(() -> BalancedAddressManager.getBaln()).thenReturn(tokenScore.getAddress()); bBalnScore = sm.deploy(owner, BoostedBalnImpl.class, mockBalanced.governance.getAddress(), bBalnSymbol); diff --git a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/StateMachineTest.java b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/StateMachineTest.java index e6d394dec..c02784a05 100644 --- a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/StateMachineTest.java +++ b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/StateMachineTest.java @@ -32,14 +32,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.*; @DisplayName("Statemachine Tests") public class StateMachineTest extends AbstractBoostedBalnTest { private static final Long WEEK = 7 * 86400L * 1000000L; private static final Long MAX_TIME = 4 * 365 * 86400L * 1000000L; private static final BigInteger MINT_AMOUNT = BigInteger.TEN.pow(40); + private static final String NATIVE_NID = "0x1.ICON"; private static final ServiceManager sm = getServiceManager(); @@ -82,6 +82,7 @@ private void setupAccounts() { @BeforeEach public void setup() throws Exception { MockBalanced mockBalanced = new MockBalanced(sm, owner); + when(mockBalanced.xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); MockBalanced.addressManagerMock.when(() -> BalancedAddressManager.getBaln()).thenReturn(tokenScore.getAddress()); bBalnScore = sm.deploy(owner, BoostedBalnImpl.class, mockBalanced.governance.getAddress(), "bBALN"); diff --git a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/VotingPowerTest.java b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/VotingPowerTest.java index b17711717..fab3f1fef 100644 --- a/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/VotingPowerTest.java +++ b/token-contracts/bBaln/src/test/java/network/balanced/score/tokens/VotingPowerTest.java @@ -36,8 +36,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.*; /** * Test voting power in the following scenario. @@ -78,6 +77,7 @@ public class VotingPowerTest extends AbstractBoostedBalnTest { public static BigInteger WEEK = DAY.multiply(BigInteger.valueOf(7L)); public static BigInteger YEAR = DAY.multiply(BigInteger.valueOf(365L)); public static BigInteger MAX_TIME = YEAR.multiply(BigInteger.valueOf(4L)); + private static final String NATIVE_NID = "0x1.ICON"; private BoostedBalnImpl scoreSpy; @@ -85,6 +85,7 @@ public class VotingPowerTest extends AbstractBoostedBalnTest { public void setup() throws Exception { tokenScore = sm.deploy(owner, IRC2Token.class, INITIAL_SUPPLY); MockBalanced mockBalanced = new MockBalanced(sm, owner); + when(mockBalanced.xCall.mock.getNetworkId()).thenReturn(NATIVE_NID); MockBalanced.addressManagerMock.when(() -> BalancedAddressManager.getBaln()).thenReturn(tokenScore.getAddress()); bBALNScore = sm.deploy(owner, BoostedBalnImpl.class, mockBalanced.governance.getAddress(), B_BALANCED_SYMBOL);