Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save IgorShadurin/e6aac15618128b21643117831b56a0d4 to your computer and use it in GitHub Desktop.
Save IgorShadurin/e6aac15618128b21643117831b56a0d4 to your computer and use it in GitHub Desktop.
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let ServerPublicKey = base58'kYxoGdY4mv5zMYWYJTq3Pp3uLDuLphTYfT8epjYEJvy'
let ServerAddress = addressFromStringValue("3MuJmCSEUgBNy1R2gesk59xDbWcuTKwwixW")
let RouletteSections = 21
let DataGameNumberKey = "APP_GAME_ID"
let DataUserGameKey = "USER_GAME_ID_"
let DataAmountKey = "AMOUNT"
let DataSectionKey = "SECTION"
let DataStatusKey = "STATUS"
let DataResultKey = "RESULT"
let DataWinAmountKey = "WIN_AMOUNT"
let DataStatusNew = "NEW"
let DataStatusWin = "WIN"
let DataStatusLoose = "LOOSE"
let WAVELET = ((100 * 1000) * 1000)
let COMMISSION = ((5 * WAVELET) / 1000)
let BET1 = (1 * WAVELET)
let BET2 = (2 * WAVELET)
let BET4 = (4 * WAVELET)
let BET8 = (8 * WAVELET)
let BET14 = (14 * WAVELET)
let Sections = [0,2,20,2,5,2,10,2,6,2,5,2,6,2,5,2,10,2,5,2,6]
let ErrorOnlyWavesAccepted = "Only waves accepted"
let ErrorMustGreaterThan0 = "Parameter size must be greater than 0"
let ErrorMustLessThan100 = "Parameter size must be less than 100"
let ErrorBetMustBeInWaves = "Bet amount must be in Waves"
let ErrorTransactionMustBeInWaves = "Transaction's fee must be in Waves"
let ErrorTransactionUsed = "Passed txId had been used before. Game aborted."
let ErrorKeyNotFound = "Key not found: "
let ErrorGameOver = "Game already is over "
let ErrorIncorrectSectionResult = "Incorrect section result"
let ErrorBetAmountNotInRange = "Bet amount is not in range"
func StoreData(transactionId: String, key: String, value: String)={
DataEntry(transactionId + "_" + key, value)
}
func StoreDataInt(transactionId: String, key: String, value: Int)={
DataEntry(transactionId + "_" + key, value)
}
func GetData(key: String) = {
match getString(this, key) {
case str: String => str
case _ => throw(ErrorKeyNotFound + key)
}
}
func GetDataString(transactionId: String, key: String) = {
let fullKey = transactionId + "_" + key
match getString(this, fullKey) {
case str: String => str
case _ => throw(ErrorKeyNotFound + fullKey)
}
}
func GetDataInt(transactionId: String, key: String) = {
let fullKey = transactionId + "_" + key
match getInteger(this, fullKey) {
case str: Int => str
case _ => throw(ErrorKeyNotFound + fullKey)
}
}
func NewGameId () = {
let gameNum = match getInteger(this, DataGameNumberKey) {
case num: Int => num
case _ => 0
}
(gameNum + 1)
}
func GenerateRandInt (gameId: String, rsaSign: String) = {
let rsaSigValid = sigVerify(fromBase58String(gameId), fromBase58String(rsaSign), ServerPublicKey);
if (rsaSigValid) then
{
let rand = (toInt(sha256(toBytes(rsaSign))) % RouletteSections)
if ((0 > rand))
then (-1 * rand)
else rand
}
else throw("Invalid RSA signature")
}
func GetStatus(result: Boolean) = {
if(result) then DataStatusWin
else DataStatusLoose
}
func GetWinAmount (betAmt: Int, section: Int) = {
#let isIncorrectResult = section <= 0 || section > 20
let isCorrectResult = if (if (if (if ((section == 2))
then true
else (section == 5))
then true
else (section == 6))
then true
else (section == 10))
then true
else (section == 20)
let betAmtValid = if (if (if (if ((betAmt == (BET1 + COMMISSION)))
then true
else (betAmt == (BET2 + COMMISSION)))
then true
else (betAmt == (BET4 + COMMISSION)))
then true
else (betAmt == (BET8 + COMMISSION)))
then true
else (betAmt == (BET14 + COMMISSION))
if (!isCorrectResult) then throw(ErrorIncorrectSectionResult)
else if(betAmtValid) then (betAmt - COMMISSION) * section
else throw(ErrorBetAmountNotInRange)
}
@Callable(i)
func bet(expectedResult: Int) = {
let gameNumber = NewGameId()
let gameTransactionId = toBase58String(i.transactionId)
let address = toBase58String(i.caller.bytes)
let pmt = extract(i.payment)
let txIdUsed = isDefined(getString(this, gameTransactionId))
let betNotInWaves = isDefined(pmt.assetId)
let feeNotInWaves = isDefined(pmt.assetId)
let amount = pmt.amount;
let winAmt = GetWinAmount(pmt.amount, expectedResult)
if (betNotInWaves) then throw(ErrorBetMustBeInWaves)
else if (feeNotInWaves) then throw(ErrorTransactionMustBeInWaves)
else if (txIdUsed) then throw(ErrorTransactionUsed)
else {
ScriptResult(
WriteSet([
DataEntry(DataUserGameKey + toString(gameNumber), gameTransactionId),
DataEntry(gameTransactionId, address),
DataEntry(DataGameNumberKey, gameNumber),
StoreDataInt(gameTransactionId, DataAmountKey, amount),
StoreDataInt(gameTransactionId, DataSectionKey, expectedResult),
StoreData(gameTransactionId, DataStatusKey, DataStatusNew),
StoreDataInt(gameTransactionId, DataWinAmountKey, winAmt)
]),
TransferSet([
ScriptTransfer(ServerAddress, COMMISSION, unit)
])
)
}
}
@Callable(i)
func result(gameTransactionId: String, rsa: String) = {
let randIndex = GenerateRandInt(gameTransactionId, rsa)
let selectedSection = GetDataInt(gameTransactionId, DataSectionKey)
let status = GetDataString(gameTransactionId, DataStatusKey)
if (status == DataStatusNew) then {
let randSection = Sections[randIndex]
let isWin = randSection == selectedSection
let writeSet = WriteSet([
StoreData(gameTransactionId, DataStatusKey, GetStatus(isWin)),
StoreDataInt(gameTransactionId, DataResultKey, randSection)
])
if(isWin) then {
let wallet = GetData(gameTransactionId)
let winAmount = GetDataInt(gameTransactionId, DataWinAmountKey)
ScriptResult(
writeSet,
TransferSet([
ScriptTransfer(addressFromStringValue(wallet), winAmount, unit)
])
)
} else {
writeSet
}
} else throw(ErrorGameOver + status)
}
@Verifier(tx)
func verify() = if (sigVerify(tx.bodyBytes, getElement(tx.proofs, 0), tx.senderPublicKey))
then match tx {
#case ttx: TransferTransaction => ((wavesBalance(this) - ttx.amount) >= 0)
case ttx: TransferTransaction => true
case stx: SetScriptTransaction => true
case _ => false
}
else false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment