diff --git a/ride/l2mp_staking.ride b/ride/l2mp_staking.ride index 4c57827d..52b774b9 100644 --- a/ride/l2mp_staking.ride +++ b/ride/l2mp_staking.ride @@ -7,7 +7,6 @@ let SEP = "__" let scale8 = 1_0000_0000 let scale18 = 1_000_000_000_000_000_000 let scale18BigInt = scale18.toBigInt() -let ADDRESS_BYTES_SIZE = 26 let BLOCKS_IN_DAY = 1440 func throwErr(msg: String) = { @@ -22,6 +21,7 @@ let keyStartBlock = ["%s", "startBlock"].makeString(SEP) let keyTotalLpAmount = ["%s", "totalLpAmount"].makeString(SEP) let keyTotalAssetAmount = ["%s", "totalAssetAmount"].makeString(SEP) let keyTotalLockedLpAmount = ["%s", "totalLockedLpAmount"].makeString(SEP) +let keyL2mpSwapContract = ["%s", "l2mpSwapContract"].makeString(SEP) func keyUserLpAmount(userAddress: String) = ["%s%s", "userLpAmount", userAddress].makeString(SEP) func keyUserLockedLpAmount(userAddress: String) = ["%s%s", "userLockedLpAmount", userAddress].makeString(SEP) @@ -58,6 +58,7 @@ let assetIdBytes = if (assetIdString == "WAVES") then unit else assetIdString.fr let emissionPeriodInBlocks = this.getInteger(keyEmissionPeriodInBlocks).valueOrElse(BLOCKS_IN_DAY) let emissionPerBlock = this.getInteger(keyEmissionPerBlock).valueOrElse(0) let emissionPerPeriod = emissionPerBlock * emissionPeriodInBlocks +let l2mpSwapContract = this.getString(keyL2mpSwapContract).valueOrElse("") ###################### # MULTISIG FUNCTIONS # @@ -146,6 +147,13 @@ func voteINTERNAL( # MULTISIG FUNCTIONS END # ########################## +func isAddressString(addressString: String) = { + match (addressString.addressFromString()) { + case address:Address => true + case _ => false + } +} + func stringListToIntListHelper(acc: List[Int], value: String) = acc :+ value.parseIntValue() func calcTotalProfitForHeight(h: Int) = { @@ -153,7 +161,8 @@ func calcTotalProfitForHeight(h: Int) = { let startPeriod = fraction(startBlock, 1, emissionPeriodInBlocks) let elapsedPeriods = h / emissionPeriodInBlocks - startPeriod - max([0, emissionPerPeriod * elapsedPeriods]) + let profit = emissionPerPeriod * elapsedPeriods + if (profit >= 0) then profit else "calculated profit cannot be negative".throwErr() } func calcTotalProfit() = { @@ -185,6 +194,7 @@ func getCurrentPrice() = { scale18BigInt } } +let currentPrice = getCurrentPrice() func getRemainingBlocks() = { if (emissionPerBlock == 0) @@ -205,11 +215,15 @@ func getUserStakingNodesData(userAddress: String) = { } func calcAssetFromLp(lpAmount: Int) = { - max([0, fraction(lpAmount.toBigInt(), getCurrentPrice(), scale18BigInt).toInt()]) + let assetAmount = fraction(lpAmount.toBigInt(), currentPrice, scale18BigInt).toInt() + + if (assetAmount >= 0) then assetAmount else "calculated negative assetAmount".throwErr() } func calcLpFromAsset(assetAmount: Int) = { - max([0, fraction(assetAmount.toBigInt(), scale18BigInt, getCurrentPrice()).toInt()]) + let lpAmount = fraction(assetAmount.toBigInt(), scale18BigInt, currentPrice).toInt() + + if (lpAmount >= 0) then lpAmount else "calculated negative lpAmount".throwErr() } func getUserLpAmount(userAddress: String) = this.getInteger(keyUserLpAmount(userAddress)).valueOrElse(0) @@ -233,7 +247,7 @@ func getStakeActions(i: Invocation, userAddress: String) = { i.payments.size() == 1 || "should include 1 payment".throwErr(), i.payments[0].assetId == assetIdBytes || ("payment should be in " + assetIdString).throwErr(), i.payments[0].amount > 0 || "payment amount should be greater than 0", - userAddress.fromBase58String().size() == ADDRESS_BYTES_SIZE || "user address is not valid".throwErr() + userAddress.isAddressString() || "user address is not valid".throwErr() ] let paymentAmount = i.payments[0].amount @@ -251,7 +265,7 @@ func getStakeActions(i: Invocation, userAddress: String) = { keyHistory("stake", userAddress, i.transactionId), formatHistory( calcTotalProfit(), - getCurrentPrice(), + currentPrice, totalLpAmount, totalAssetAmount ) @@ -287,7 +301,7 @@ func getWithdrawActions(i: Invocation, lpAssetWithdrawAmount: Int) = { keyHistory("withdraw", userAddress, i.transactionId), formatHistory( calcTotalProfit(), - getCurrentPrice(), + currentPrice, totalLpAmount, totalAssetAmount ) @@ -303,8 +317,8 @@ func getWithdrawActions(i: Invocation, lpAssetWithdrawAmount: Int) = { func getSetStakingNodeActions(userAddress: String, nodeAddress: String, nodeShare: Int) = { strict check = [ - userAddress.fromBase58String().size() == ADDRESS_BYTES_SIZE || "user address is not valid".throwErr(), - nodeAddress.fromBase58String().size() == ADDRESS_BYTES_SIZE || "node address is not valid".throwErr() + userAddress.isAddressString() || "user address is not valid".throwErr(), + nodeAddress.isAddressString() || "node address is not valid".throwErr() ] [ @@ -316,13 +330,14 @@ func getSetStakingNodeActions(userAddress: String, nodeAddress: String, nodeShar @Callable(i) func setEmissionPerBlock(emissionPerBlock: Int) = { strict check = [ - i.caller == this || "permission denied".throwErr() + i.caller == this || "permission denied".throwErr(), + emissionPerBlock >= 0 || "emissionPerBlock cannot be negative".throwErr() ] [ IntegerEntry(keyTotalAssetAmount, getTotalAssetAmountWithProfitOrMaxAvailable()), IntegerEntry(keyStartBlock, height), - IntegerEntry(keyEmissionPerBlock, max([0, emissionPerBlock])) + IntegerEntry(keyEmissionPerBlock, emissionPerBlock) ] } @@ -358,7 +373,7 @@ func withdraw(withdrawAssetAmount: Int) = { let userLpAmount = getUserLpAmount(userAddress) let lpAmountToWithdraw = calcLpFromAsset(withdrawAssetAmount) let userAvailableAssetToWithdraw = getUserAvailableAssetsToWithdraw(userAddress) - let minWithdrawAssetAmount = fraction(getCurrentPrice(), 1.toBigInt(), scale18BigInt, CEILING).toInt() + let minWithdrawAssetAmount = fraction(currentPrice, 1.toBigInt(), scale18BigInt, CEILING).toInt() strict check = [ withdrawAssetAmount > 0 || "withdraw amount should be more than 0".throwErr(), withdrawAssetAmount <= userAvailableAssetToWithdraw || ("cannot withdraw more than available (" + userAvailableAssetToWithdraw.toString() + ")").throwErr(), @@ -386,7 +401,8 @@ func stakeAndSetStakingNode(nodeAddress: String) = { @Callable(i) func stakeForSwapHELPER(userAddress: String, nodeAddress: String) = { strict check = [ - i.originCaller.toString() == userAddress || "i.originCaller should be equal to userAddress".throwErr() + i.originCaller.toString() == userAddress || "i.originCaller should be equal to userAddress".throwErr(), + l2mpSwapContract == "" || i.caller.toString() == l2mpSwapContract || "i.caller should be equal l2mpSwapContract".throwErr() ] let setStakingNodeActions = if (nodeAddress == "") then [] else getSetStakingNodeActions(userAddress, nodeAddress, 100) @@ -413,12 +429,10 @@ func airdrop(addressList: List[String], amountList: List[Int]) = { let (result, index, totalLp, processedList) = accum let addressString = addressList[index] - let address = match (addressString.addressFromString()) { - case adr:Address => adr - case _ => "invalid address in addressList".throwErr() - } + let address = addressString.addressFromString() strict ch = [ + isAddressString(addressString) || "invalid address in addressList".throwErr(), !processedList.containsElement(address) || "duplicate address is addressList".throwErr() ] @@ -470,7 +484,7 @@ func getUserAssetsREADONLY(userAddress: String) = { ( userLpAmount, userAvailableAssetToWithdraw, - getCurrentPrice(), + currentPrice, userTotalStakedAmount, userTotalAssetWithdrawn, userLockedLpAmount, @@ -496,7 +510,7 @@ func getTotalAssetsREADONLY() = { ( totalLpAmount, getTotalAssetAmountWithProfitOrMaxAvailable(), - getCurrentPrice(), + currentPrice, totalLockedLpAmount, calcAssetFromLp(totalLockedLpAmount), getRemainingBlocks() @@ -536,4 +550,4 @@ func verify() = { }) byAdmins || byOwner -} \ No newline at end of file +} diff --git a/ride/l2mp_swap.ride b/ride/l2mp_swap.ride index a4c4a7f1..ded7e897 100644 --- a/ride/l2mp_swap.ride +++ b/ride/l2mp_swap.ride @@ -145,7 +145,7 @@ func voteINTERNAL( } func getSwapActions(i: Invocation, stake: Boolean, stakingNode: String) = { - let userAddress = i.caller + let userAddress = i.caller let paymentSizeExpected = 1 if (i.payments.size() != paymentSizeExpected) then throwErr("invalid payments") else let payment = i.payments[0] diff --git a/test/components/l2mp_swap/_hooks.mjs b/test/components/l2mp_swap/_hooks.mjs index 2140454f..cd0be5f0 100644 --- a/test/components/l2mp_swap/_hooks.mjs +++ b/test/components/l2mp_swap/_hooks.mjs @@ -100,6 +100,18 @@ export const mochaHooks = { chainId, }, this.accounts.l2mpSwap.seed)); + await broadcastAndWait(data({ + additionalFee: 4e5, + data: [ + { + key: '%s__l2mpSwapContract', + type: 'string', + value: this.accounts.l2mpSwap.addr, + }, + ], + chainId, + }, this.accounts.l2mpStaking.seed)); + await setScriptFromFile(l2mpSwapPath, this.accounts.l2mpSwap.seed); await setScriptFromFile(l2mpStakingMockPath, this.accounts.l2mpStaking.seed); }, diff --git a/test/components/l2mp_swap/mock/l2mp_staking.mock.ride b/test/components/l2mp_swap/mock/l2mp_staking.mock.ride index 3d3376f6..89a660a0 100644 --- a/test/components/l2mp_swap/mock/l2mp_staking.mock.ride +++ b/test/components/l2mp_swap/mock/l2mp_staking.mock.ride @@ -3,6 +3,10 @@ {-# SCRIPT_TYPE ACCOUNT #-} let contractFile = "l2mp_staking.ride" +let SEP = "__" + +let keyL2mpSwapContract = ["%s", "l2mpSwapContract"].makeString(SEP) +let l2mpSwapContract = this.getString(keyL2mpSwapContract).valueOrElse("") func wrapErr(msg: String) = { contractFile + ": " + msg @@ -20,7 +24,8 @@ func stakeFor(userAddressStr: String) = { @Callable(i) func stakeForSwapHELPER(userAddress: String, nodeAddress: String) = { strict check = [ - i.originCaller.toString() == userAddress || "i.originCaller should be equal to userAddress".throwErr() + i.originCaller.toString() == userAddress || "i.originCaller should be equal to userAddress".throwErr(), + l2mpSwapContract == "" || i.caller.toString() == l2mpSwapContract || "i.caller should be equal l2mpSwapContract".throwErr() ] (nil, unit)