Skip to content

Commit 6cc3af0

Browse files
authored
Merge pull request #467 from balancednetwork/feat/crosschain_savings
feat: Feat/crosschain savings
2 parents f2b0652 + 3d864ec commit 6cc3af0

11 files changed

Lines changed: 708 additions & 59 deletions

File tree

core-contracts/Router/src/main/java/network/balanced/score/core/router/RouterImpl.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,18 @@ public void xTokenFallback(String _from, BigInteger _value, byte[] _data) {
245245
executeRoute(_from, _data);
246246
}
247247

248+
private RouteData getRouteData(byte[] data){
249+
RouteData routeData;
250+
try {
251+
routeData = RouteData.fromBytes(data);
252+
}catch(IllegalStateException ignored ){
253+
routeData = RouteData.fromBytesOld(data);
254+
}
255+
return routeData;
256+
}
257+
248258
private void executeRoute(String _from, byte[] data) {
249-
RouteData routeData = RouteData.fromBytes(data);
259+
RouteData routeData = getRouteData(data);
250260
Context.require(routeData.method.contains("_swap"), TAG + ": Fallback directly not allowed.");
251261

252262
Address fromToken = Context.getCaller();
@@ -261,8 +271,11 @@ private void executeRoute(String _from, byte[] data) {
261271
} else {
262272
receiver = _from;
263273
}
264-
265-
route(receiver, fromToken, routeData.actions, minimumReceive, EMPTY_DATA);
274+
byte[] _data = EMPTY_DATA;
275+
if(routeData.data!=null){
276+
_data = routeData.data;
277+
}
278+
route(receiver, fromToken, routeData.actions, minimumReceive, _data);
266279
}
267280

268281
private void jsonRoute(String _from, byte[] data) {
@@ -308,7 +321,11 @@ private void jsonRoute(String _from, byte[] data) {
308321
}
309322

310323
Address fromToken = Context.getCaller();
311-
route(receiver, fromToken, actions, minimumReceive, EMPTY_DATA);
324+
byte[] _data = EMPTY_DATA;
325+
if(params.contains("data")){
326+
_data = params.get("data").asString().getBytes();
327+
}
328+
route(receiver, fromToken, actions, minimumReceive, _data);
312329
}
313330

314331
@Payable
@@ -318,4 +335,4 @@ public void fallback() {
318335
@EventLog(indexed = 1)
319336
public void Route(Address from, BigInteger fromAmount, Address to, BigInteger toAmount) {
320337
}
321-
}
338+
}

core-contracts/Router/src/test/java/network/balanced/score/core/router/RouterTest.java

Lines changed: 108 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,10 @@
2828
import network.balanced.score.lib.structs.RouteData;
2929
import network.balanced.score.lib.test.mock.MockBalanced;
3030
import network.balanced.score.lib.test.mock.MockContract;
31-
import network.balanced.score.lib.tokens.HubTokenImpl;
32-
import network.balanced.score.lib.tokens.IRC2Base;
33-
import network.balanced.score.lib.tokens.IRC2Mintable;
3431
import org.junit.jupiter.api.BeforeEach;
3532
import org.junit.jupiter.api.Test;
3633
import org.junit.jupiter.api.function.Executable;
3734
import score.Address;
38-
import score.Context;
3935
import scorex.util.ArrayList;
4036

4137
import java.math.BigInteger;
@@ -44,11 +40,8 @@
4440

4541
import static network.balanced.score.core.router.RouterImpl.*;
4642
import static network.balanced.score.lib.test.UnitTest.*;
47-
import static network.balanced.score.lib.utils.Constants.EXA;
4843
import static org.junit.jupiter.api.Assertions.assertEquals;
4944
import static org.junit.jupiter.api.Assertions.assertThrows;
50-
import static org.mockito.ArgumentMatchers.any;
51-
import static org.mockito.ArgumentMatchers.eq;
5245
import static org.mockito.Mockito.verify;
5346
import static org.mockito.Mockito.when;
5447

@@ -182,14 +175,7 @@ void tokenFallback() throws Exception {
182175
when(balanced.baln.mock.balanceOf(routerScore.getAddress())).thenReturn(BigInteger.TEN);
183176
when(balanced.sicx.mock.balanceOf(routerScore.getAddress())).thenReturn(BigInteger.TEN);
184177

185-
// byte[] invalidPathWithSicxTerminalToken = tokenData("_swap", Map.of("path",
186-
// new Object[]{balanced.baln.getAddress().toString(), null}));
187-
// Executable nonSicxIcxTrade = () -> routerScore.invoke(sicxScore.account, "tokenFallback", owner.getAddress(),
188-
// BigInteger.TEN, invalidPathWithSicxTerminalToken);
189-
// expectedErrorMessage = "Reverted(0): " + TAG + ": Native swaps not available to icon from " + balanced.baln.getAddress();
190-
// expectErrorMessage(nonSicxIcxTrade, expectedErrorMessage);
191-
//
192-
// resetInRoute();
178+
193179
Account newReceiver = sm.createAccount();
194180
byte[] pathWithSicxTerminalToken = tokenData("_swap", Map.of("path",
195181
new Object[]{sicxScore.getAddress().toString(), null}, "receiver",
@@ -501,7 +487,42 @@ void tokenFallback_swapStable() throws Exception {
501487
}
502488

503489
Account newReceiver = sm.createAccount();
504-
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions).toBytes();
490+
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions, null).toBytes();
491+
492+
// Act
493+
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), balnToSwap,
494+
data);
495+
496+
// Assert
497+
int i = 0;
498+
for (MockContract<IRC2> token : tokens) {
499+
if (i < tokens.size() - 1) {
500+
byte[] d = tokens.get(i + 1).getAddress().toString().getBytes();
501+
verify(token.mock).transfer(balanced.stability.getAddress(), balnToSwap, d);
502+
}
503+
i++;
504+
}
505+
}
506+
507+
@Test
508+
void tokenFallback_swapStableOldRouteData() throws Exception {
509+
// Arrange
510+
BigInteger balnToSwap = BigInteger.TEN.multiply(ICX);
511+
List<RouteAction> actions = new ArrayList<>(MAX_NUMBER_OF_ITERATIONS);
512+
List<MockContract<IRC2>> tokens = new ArrayList<>(MAX_NUMBER_OF_ITERATIONS - 1);
513+
for (int i = 0; i < MAX_NUMBER_OF_ITERATIONS; i++) {
514+
if (i == 0) {
515+
actions.add(new RouteAction(SWAP, balanced.sicx.getAddress()));
516+
continue;
517+
}
518+
MockContract<IRC2> token = new MockContract<>(IRC2ScoreInterface.class, IRC2.class, sm, owner);
519+
when(token.mock.balanceOf(routerScore.getAddress())).thenReturn(balnToSwap);
520+
actions.add(new RouteAction(STABILITY_SWAP, token.getAddress()));
521+
tokens.add(token);
522+
}
523+
524+
Account newReceiver = sm.createAccount();
525+
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions, null).toBytesOld();
505526

506527
// Act
507528
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), balnToSwap,
@@ -531,7 +552,30 @@ void tokenFallback_swapToICX() throws Exception {
531552
routerScore.getAccount().addBalance("ICX", ICXResult);
532553

533554
Account newReceiver = sm.createAccount();
534-
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions).toBytes();
555+
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions, null).toBytes();
556+
557+
// Act
558+
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), USDToSwap,
559+
data);
560+
561+
// Assert
562+
assertEquals(ICXResult, newReceiver.getBalance());
563+
}
564+
565+
@Test
566+
void tokenFallback_swapToICXOldRouteData() throws Exception {
567+
// Arrange
568+
BigInteger USDToSwap = BigInteger.TEN.multiply(ICX);
569+
BigInteger sICXResult = BigInteger.valueOf(100).multiply(ICX);
570+
BigInteger ICXResult = BigInteger.valueOf(110).multiply(ICX);
571+
List<RouteAction> actions = new ArrayList<>(2);
572+
actions.add(new RouteAction(SWAP, balanced.sicx.getAddress()));
573+
actions.add(new RouteAction(SWAP, null));
574+
when(balanced.sicx.mock.balanceOf(routerScore.getAddress())).thenReturn(sICXResult);
575+
routerScore.getAccount().addBalance("ICX", ICXResult);
576+
577+
Account newReceiver = sm.createAccount();
578+
byte[] data = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions, null).toBytesOld();
535579

536580
// Act
537581
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), USDToSwap,
@@ -586,4 +630,51 @@ private void resetInRoute() {
586630
// in Production this happens between each tx
587631
((RouterImpl)routerScore.getInstance()).inRoute = false;
588632
}
633+
634+
@Test
635+
void stakeToSavingsWithJSONRoute(){
636+
// Arrange
637+
//baln as usdc
638+
when(balanced.baln.mock.balanceOf(routerScore.getAddress())).thenReturn(BigInteger.TEN);
639+
when(balanced.bnUSD.mock.balanceOf(routerScore.getAddress())).thenReturn(BigInteger.TEN);
640+
641+
String data = new String(tokenData("_lock", Map.of()));
642+
Account newReceiver = balanced.savings.account;
643+
byte[] pathWithUSDCBnUSD = tokenData("_swap", Map.of("path",
644+
new Object[]{balanced.bnUSD.getAddress().toString()}, "receiver",
645+
newReceiver.getAddress().toString(), "data", data));
646+
647+
// Act
648+
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), BigInteger.TEN,
649+
pathWithUSDCBnUSD);
650+
651+
652+
// Verify
653+
verify(balanced.bnUSD.mock).transfer(balanced.savings.getAddress(), BigInteger.TEN, data.getBytes());
654+
}
655+
656+
@Test
657+
void stakeToSavingsWithRLPData(){
658+
// Arrange
659+
//baln as usdc
660+
BigInteger balnToSwap = BigInteger.TEN.multiply(ICX);
661+
when(balanced.baln.mock.balanceOf(routerScore.getAddress())).thenReturn(balnToSwap);
662+
when(balanced.bnUSD.mock.balanceOf(routerScore.getAddress())).thenReturn(balnToSwap);
663+
664+
List<RouteAction> actions = new ArrayList<>(1);
665+
actions.add(new RouteAction(SWAP, balanced.bnUSD.getAddress()));
666+
667+
byte[] data = tokenData("_lock", Map.of());
668+
Account newReceiver = balanced.savings.account;
669+
byte[] routeData = new RouteData("_swap", newReceiver.getAddress().toString(), BigInteger.ZERO, actions, data).toBytes();
670+
671+
// Act
672+
routerScore.invoke(balanced.baln.account, "tokenFallback", owner.getAddress(), balnToSwap,
673+
routeData);
674+
675+
676+
// Verify
677+
verify(balanced.bnUSD.mock).transfer(balanced.savings.getAddress(), balnToSwap, data);
678+
}
679+
589680
}

core-contracts/Savings/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ dependencies {
3030
implementation Dependencies.javaeeScorex
3131
implementation Dependencies.minimalJson
3232
implementation project(':score-lib')
33+
implementation 'xyz.venture23:xcall-lib:2.1.0'
3334

3435
testImplementation Dependencies.javaeeUnitTest
3536
testImplementation Dependencies.javaeeTokens

0 commit comments

Comments
 (0)