Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L2mp staking/swap issue #426 #429

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 34 additions & 20 deletions ride/l2mp_staking.ride
Original file line number Diff line number Diff line change
Expand Up @@ -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) = {
Expand All @@ -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)
Expand Down Expand Up @@ -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 #
Expand Down Expand Up @@ -146,14 +147,22 @@ 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) = {
let startBlock = this.getInteger(keyStartBlock).valueOrElse(height)
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() = {
Expand Down Expand Up @@ -185,6 +194,7 @@ func getCurrentPrice() = {
scale18BigInt
}
}
let currentPrice = getCurrentPrice()

func getRemainingBlocks() = {
if (emissionPerBlock == 0)
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -251,7 +265,7 @@ func getStakeActions(i: Invocation, userAddress: String) = {
keyHistory("stake", userAddress, i.transactionId),
formatHistory(
calcTotalProfit(),
getCurrentPrice(),
currentPrice,
totalLpAmount,
totalAssetAmount
)
Expand Down Expand Up @@ -287,7 +301,7 @@ func getWithdrawActions(i: Invocation, lpAssetWithdrawAmount: Int) = {
keyHistory("withdraw", userAddress, i.transactionId),
formatHistory(
calcTotalProfit(),
getCurrentPrice(),
currentPrice,
totalLpAmount,
totalAssetAmount
)
Expand All @@ -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()
]

[
Expand All @@ -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)
]
}

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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)
Expand All @@ -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()
]

Expand Down Expand Up @@ -470,7 +484,7 @@ func getUserAssetsREADONLY(userAddress: String) = {
(
userLpAmount,
userAvailableAssetToWithdraw,
getCurrentPrice(),
currentPrice,
userTotalStakedAmount,
userTotalAssetWithdrawn,
userLockedLpAmount,
Expand All @@ -496,7 +510,7 @@ func getTotalAssetsREADONLY() = {
(
totalLpAmount,
getTotalAssetAmountWithProfitOrMaxAvailable(),
getCurrentPrice(),
currentPrice,
totalLockedLpAmount,
calcAssetFromLp(totalLockedLpAmount),
getRemainingBlocks()
Expand Down Expand Up @@ -536,4 +550,4 @@ func verify() = {
})

byAdmins || byOwner
}
}
2 changes: 1 addition & 1 deletion ride/l2mp_swap.ride
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
12 changes: 12 additions & 0 deletions test/components/l2mp_swap/_hooks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},
Expand Down
7 changes: 6 additions & 1 deletion test/components/l2mp_swap/mock/l2mp_staking.mock.ride
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading