def Main(op, args):
    context = GetContext()

    if op == 'registerDelegator':
        if len(args) == 2:
            return register_delegator(context, args)
        else:
            Notify(ARG_ERROR)
            return False
    elif op == 'registerWallet':
        if len(args) == 1:
            return register_wallet(context, args)
        else:
            Notify(ARG_ERROR)
            return False
    elif op == 'verifyClaim':
        if len(args) == 1:
            delegator = GetEntryScriptHash()
            return verify_claim(context, delegator, args)
        else:
            Notify(ARG_ERROR)
            return False
    else:
        Notify(INVALID_OPERATION)
        return False
Exemple #2
0
def checkHash():
    Notify(["111_checkHash"])
    # to prevent hack from other contract
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    Notify([callerHash, entryHash, ContractAddress])
    return True
Exemple #3
0
def invokeB(param):
    Notify(["111_invokeB", param])
    # to prevent hack from other contract
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    Notify([callerHash, entryHash, ContractAddress])
    return True
Exemple #4
0
def do_transfer(ctx, Caller, args):
    """Transfers a token at the specified id from the t_owner address
    to the t_to address

    :param StorageContext ctx: current store context
    :param list args:
        0: bytearray t_to: transfer to address
        1: int t_id: token id
    :return: transfer success
    :rtype: bool
    """
    # we don't need the t_from because the token data stores the owner
    t_from = ""
    t_to = args[0]
    t_id = args[1]

    if len(
            args
    ) == 3:  # use traditional from, to, id format if they want to send it
        t_from = args[0]
        t_to = args[1]
        t_id = args[2]

    if Caller != GetEntryScriptHash() and not is_whitelisted_dex(ctx, Caller):
        # non-whitelisted contracts can only approve their own funds for transfer,
        # even if they have the signature of the owner on the invocation
        t_from = Caller

    assert len(t_to) == 20, INVALID_ADDRESS_ERROR
    ownership = safe_deserialize(Get(ctx, concat('ownership/', t_id)))

    assert ownership, TOKEN_DNE_ERROR
    assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR
    assert len(ownership['owner']) == 20, TOKEN_DNE_ERROR

    t_owner = ownership['owner']

    if t_owner == t_to:
        print('transfer to self')
        return True

    assert authenticate(t_owner, Caller), PERMISSION_ERROR

    res = remove_token_from_owners_list(ctx, t_owner, t_id)
    assert res, 'unable to remove token from owner list'

    ownership['owner'] = t_to  # update token's owner
    # remove any existing approvals for this token
    if has_key(ownership, 'approved'):
        ownership.remove('approved')

    Put(ctx, concat('ownership/', t_id), Serialize(ownership))
    res = add_token_to_owners_list(ctx, t_to, t_id)

    # log this transfer event
    OnTransfer(t_owner, t_to, 1)
    OnNFTTransfer(t_owner, t_to, t_id)
    return True
Exemple #5
0
def avoidToBeInvokedByContract():
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    if callerHash != entryHash:
        Notify(["You are not allowed to invoke this method through contract"])
        return False
    else:
        Notify(["You can implement what you need to do here!"])
        return True
Exemple #6
0
def do_approve(ctx, caller, t_receiver, t_id, revoke):
    """Approve a token to eventually be transferred to the t_receiver

    :param StorageContext ctx: current store context
    :param byte[] caller: calling script hash
    :param byte[] t_receiver: address of the future token owner
    :param bytes t_id: int: token id
    :param bytes revoke: set to 1 to revoke previous approval
    :return: approval success
    :rtype: bool
    """
    if len(t_receiver) != 20:
        Notify(INVALID_ADDRESS_ERROR)
        return False

    if len(revoke) == b'\x00':
        revoke = b'\x00'

    t_owner = Get(ctx, t_id)
    if len(t_owner) != 20:
        Notify(TOKEN_DNE_ERROR)
        return False

    if t_owner == t_receiver:
        Notify('approved spend to self')
        return True

    is_token_owner = CheckWitness(t_owner)
    if is_token_owner and GetEntryScriptHash() != caller:
        Notify('third party script is bouncing the signature to us')
        return False
    # if token owner is a smart contract and is the calling
    # script hash, continue
    elif GetContract(t_owner) and t_owner == caller:
        is_token_owner = True

    if is_token_owner:
        approval_key = concat('approved/', t_id)
        # revoke previous approval if revoke != 0
        if revoke != b'\x00':
            Delete(ctx, approval_key)
            # log the revoking of previous approvals
            OnApprove(t_owner, t_receiver, b'\x00')
            OnNFTApprove(t_owner, '', t_id)
            return True

        # approve this transfer
        Put(ctx, approval_key, concat(t_owner, t_receiver))

        # Log this approval event
        OnApprove(t_owner, t_receiver, 1)
        OnNFTApprove(t_owner, t_receiver, t_id)
        return True

    Notify(PERMISSION_ERROR)
    return False
Exemple #7
0
def do_approve(ctx, Caller, args):
    """Approve a token to be transferred to a third party by an approved spender

    :param StorageContext ctx: current store context
    :param bytearray t_owner: current owner of the token
    :param bytearray t_spender: spender to approve
    :param int t_id: int: token id
    :param bool revoke: set to True to revoke previous approval
    :return: approval success
    :rtype: bool
    """
    t_owner = args[0]
    t_spender = args[1]
    t_id = args[2]
    revoke = False

    if len(args) > 3:
        revoke = args[3]

    if Caller != GetEntryScriptHash() and not is_whitelisted_dex(ctx, Caller):
        # non-whitelisted contracts can only approve their own funds for transfer,
        # even if they have the signature of the owner on the invocation
        t_owner = Caller

    assert len(t_owner) == 20, INVALID_ADDRESS_ERROR
    assert len(t_spender) == 20, INVALID_ADDRESS_ERROR
    assert t_id, TOKEN_DNE_ERROR

    ownership_key = concat('ownership/', t_id)
    ownership = safe_deserialize(Get(ctx, ownership_key))

    assert ownership, TOKEN_DNE_ERROR
    assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR
    assert t_owner == ownership['owner'], PERMISSION_ERROR
    assert t_owner != t_spender, 'same owner and spender'
    assert authenticate(t_owner, Caller), PERMISSION_ERROR

    # revoke previous approval if revoke is True
    if revoke:
        if has_key(ownership, 'approved'):
            ownership.remove('approved')
            Put(ctx, ownership_key, Serialize(ownership))

        # log the revoking of previous approvals
        OnApprove(t_owner, t_spender, 0)
        OnNFTApprove(t_owner, '', t_id)
        return True

    ownership['approved'] = concat(t_owner, t_spender)
    # approve this transfer
    Put(ctx, ownership_key, Serialize(ownership))
    # Log this approval event
    OnApprove(t_owner, t_spender, 1)
    OnNFTApprove(t_owner, t_spender, t_id)
    return True
Exemple #8
0
def do_transfer(ctx, t_from, t_to, amount, callingScriptHash):

    if amount <= 0:
        return False

    if len(t_to) != 20:
        return False

    # if the calling script hash is not the entry script hash
    # we force the `t_from` to be the address of the callingScriptHash
    if callingScriptHash != GetEntryScriptHash():
        print("Cannot call from another contract on behalf of other addresses")
        print("Setting from address to callingScriptHash")
        t_from = callingScriptHash
    else:
        if t_from == GetExecutingScriptHash():

            if not check_owners(ctx, 3):
                print("Must authenticate as owners")
                return False

        else:
            if not CheckWitness(t_from):
                print("Insufficient priveleges")
                return False

    from_balance_key = get_balance_key(t_from)
    to_balance_key = get_balance_key(t_to)

    from_balance = Get(ctx, from_balance_key)

    if from_balance < amount:
        Notify("insufficient funds")
        return False

    if t_from == t_to:
        return True

    if from_balance == amount:
        Delete(ctx, from_balance_key)

    else:
        difference = from_balance - amount
        Put(ctx, from_balance_key, difference)

    to_balance = Get(ctx, to_balance_key)

    to_total = to_balance + amount

    Put(ctx, to_balance_key, to_total)

    OnTransfer(t_from, t_to, amount)

    return True
def avoidContractCallAttack(guessNumber):

    randomNumber = getRandomNumber()

    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    Notify(["randomNumber:", randomNumber, "guessNumber:", guessNumber])
    if callerHash != entryHash:
        Notify(["You are not allowed to invoke this method through contract!"])
        return False
    else:
        Notify(["You can implement what you need to do here!"])
        if guessNumber == randomNumber:
            Notify(["You have won the big prize!"])
        return True
Exemple #10
0
def do_approve(ctx, t_owner, t_spender, amount, callingScriptHash):

    if t_owner == GetExecutingScriptHash():
        print("Cannot approve from contract address. Use transfer")
        return False

    # if the calling script hash is not the entry script hash
    # we force the `t_from` to be the address of the callingScriptHash
    if callingScriptHash != GetEntryScriptHash():
        print("Cannot call from another contract on behalf of other addresses")
        print("Setting from address to callingScriptHash")
        t_owner = callingScriptHash

    else:
        if not CheckWitness(t_owner):
            print("Insufficient priveleges")
            return False

    if len(t_spender) != 20:
        return False

    if amount < 0:
        return False

    # cannot approve an amount that is
    # currently greater than the from balance
    owner_balance_key = get_balance_key(t_owner)

    if Get(ctx, owner_balance_key) >= amount:

        approval_key = get_allowance_key(t_owner, t_spender)

        if amount == 0:
            Delete(ctx, approval_key)
        else:
            Put(ctx, approval_key, amount)

        OnApprove(t_owner, t_spender, amount)

        return True

    print("not enough balance")
    return False
Exemple #11
0
def do_transfer(ctx, caller, args):
    """Transfers a token at the specified id from the t_owner address
    to the t_to address

    :param StorageContext ctx: current store context
    :param bytes caller: calling script hash
    :param list args:
        0: byte[] t_to: transfer to address
        1: bytes t_id: token id
        2: extra_arg: optional argument that can be passed (for use
            only with smart contracts)
    :return: transfer success
    :rtype: bool
    """
    t_to = args[0]
    t_id = args[1]

    if len(t_to) != 20:
        Notify(INVALID_ADDRESS_ERROR)
        return False

    t_owner = Get(ctx, t_id)
    if len(t_owner) != 20:
        Notify(TOKEN_DNE_ERROR)
        return False

    if t_owner == t_to:
        Notify('transfer to self')
        return True

    # Verifies that the calling contract has verified the required
    # script hashes of the transaction/block
    is_token_owner = CheckWitness(t_owner)
    if is_token_owner and GetEntryScriptHash() != caller:
        Notify('third party script is bouncing the signature to us')
        return False
    # if token owner is a smart contract and is the calling
    # script hash, continue
    elif GetContract(t_owner) and t_owner == caller:
        is_token_owner = True

    if is_token_owner:
        # 1. Is t_to a smart contract?
        # If True, invoke the transfer_to_smart_contract
        # method, if transfer_to_smart_contract() returns False,
        # then reject the transfer
        if GetContract(t_to):
            success = transfer_to_smart_contract(ctx, t_owner, args, False)
            if success is False:
                return False
        else:
            if len(args) > 2:
                Notify(ARG_ERROR)
                return False

        res = remove_token_from_owners_list(ctx, t_owner, t_id)
        if res is False:
            Notify('unable to transfer token')
            return False

        Put(ctx, t_id, t_to)  # update token's owner
        # remove any existing approvals for this token
        Delete(ctx, concat('approved/', t_id))
        add_token_to_owners_list(ctx, t_to, t_id)

        # log this transfer event
        OnTransfer(t_owner, t_to, 1)
        OnNFTTransfer(t_owner, t_to, t_id)
        return True

    Notify(PERMISSION_ERROR)
    return False
Exemple #12
0
def invokeA(operation, params):
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    Notify(["111_invokeA",callerHash, entryHash, ContractAddress])
    return ContractB(operation, params)
Exemple #13
0
def do_transfer_from(ctx, Caller, args):
    """Transfers the approved token at the specified id from the
    t_from address to the t_to address

    Only the approved spender OR a whitelisted DEX can invoke this function
    and a whitelisted DEX will still need to pass the authentication of the spender

    :param StorageContext ctx: current store context
    :param list args:
        0: bytearray t_spender: approved spender address
        1: bytearray t_from: transfer from address (token owner)
        2: bytearray t_to: transfer to address (token receiver)
        3: int t_id: token id
    :return: transferFrom success
    :rtype: bool
    """

    t_spender = args[0]
    t_from = args[1]
    t_to = args[2]
    t_id = args[3]

    if Caller != GetEntryScriptHash() and not is_whitelisted_dex(ctx, Caller):
        # non-whitelisted contracts can only approve their own funds for transfer,
        # even if they have the signature of the owner on the invocation
        t_from = Caller

    assert len(t_spender) == 20, INVALID_ADDRESS_ERROR
    assert len(t_from) == 20, INVALID_ADDRESS_ERROR
    assert len(t_to) == 20, INVALID_ADDRESS_ERROR
    assert authenticate(t_spender, Caller), PERMISSION_ERROR

    if t_from == t_to:
        print('transfer to self')
        return True

    ownership = safe_deserialize(Get(ctx, concat('ownership/', t_id)))
    assert ownership, TOKEN_DNE_ERROR
    assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR
    assert has_key(ownership, 'approved'), 'no approval exists for this token'
    assert len(ownership['owner']) == 20, TOKEN_DNE_ERROR

    t_owner = ownership['owner']

    assert t_from == t_owner, 'from address is not the owner of this token'
    assert len(
        ownership['approved']) == 40, 'malformed approval key for this token'

    # Finally check to see if the owner approved this spender
    assert ownership['approved'] == concat(t_from, t_spender), PERMISSION_ERROR

    res = remove_token_from_owners_list(ctx, t_from, t_id)
    assert res, 'unable to remove token from owner list'

    ownership['owner'] = t_to
    ownership.remove('approved')  # remove previous approval
    Put(ctx, concat('ownership/', t_id), Serialize(ownership))
    res = add_token_to_owners_list(ctx, t_to, t_id)

    # log this transfer event
    OnTransfer(t_from, t_to, 1)
    OnNFTTransfer(t_from, t_to, t_id)
    return True
Exemple #14
0
def bet(account, ongAmount, number):
    """
    :param account:
    :param ongAmount:
    :param number:
    :return:
    """
    # RequireWitness(account)
    if CheckWitness(account) == False:
        # bet: Check witness failed!
        Notify(["Error", 601])
        return False

    currentRound = getCurrentRound()

    # to prevent hack from other contract
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    # Require(callerHash == entryHash)
    if callerHash != entryHash:
        # bet: Don't support bet method being invoked by another contract to prevent hacking
        Notify(["Error", 602])
        return False

    if getRoundGameStatus(currentRound) != STATUS_ON:
        # bet: Current round game ended, please wait for the starting of the next round game and try later
        Notify(["Error", 603])
        return False

    # make sure the contract has enough ong to pay to accont if account wins
    tryPayOutToWin = _calculatePayOutToWin(ongAmount, number)
    totalOngAmount = getTotalONG()
    realTimeRunVault = getRealTimeRunningVault(currentRound)

    # # Require(realTimeRunVault > tryPayOutToWin)
    if realTimeRunVault < Sub(tryPayOutToWin, ongAmount):
        # bet: Running pot/vault does not have enough asset to pay to the player, please try smaller bet
        Notify(["Error", 604])
        return False

    # Require(_transferONG(account, ContractAddress, ongAmount))
    res = _transferONG(account, ContractAddress, ongAmount)
    if res == False:
        # bet: Transfer ONG failed, please try later or again
        Notify(["Error", 605])
        return False

    # Require(number < 97)
    if number >= 97:
        # bet: Please try to bet with a number less than 97
        Notify(["Error", 606])
        return False
    # Require(number > 1)
    if number <= 1:
        # bet: Please try to bet with a number greater than 1
        Notify(["Error", 607])
        return False

    theNumber = _rollANumber()
    payOutToWin = 0
    if theNumber < number:
        payOutToWin = tryPayOutToWin
        Require(_transferONGFromContact(account, payOutToWin))

        # update total ongAmount
        ongAmountToBeSub = Sub(payOutToWin, ongAmount)
        Put(GetContext(), TOTAL_ONG_KEY, Sub(totalOngAmount, ongAmountToBeSub))
        # update real time running vault
        realTimeRunVaultKey = concatKey(concatKey(ROUND_PREFIX, currentRound),
                                        REAL_TIME_RUNNING_VAULT)
        Put(GetContext(), realTimeRunVaultKey,
            Sub(realTimeRunVault, ongAmountToBeSub))
        realTimeRunVault = getRealTimeRunningVault(currentRound)
        # mark the game as end if real time running vault is less than 1/10 of running vault
        if realTimeRunVault <= Div(getIncreasingRunnVault(currentRound), 10):
            # mark this round of game end
            Put(GetContext(),
                concatKey(concatKey(ROUND_PREFIX, currentRound), ROUND_STATUS),
                STATUS_OFF)
            # update profit per investment for bankers
            runVaultLeft = getRunningVault(currentRound)
            if runVaultLeft > 0:
                profitPerRuningVaultShareToBeAdd = Div(
                    Mul(realTimeRunVault, MagnitudeForProfitPerSth),
                    runVaultLeft)
                Put(
                    GetContext(),
                    concatKey(concatKey(ROUND_PREFIX, currentRound),
                              PROFIT_PER_RUNNING_VAULT_SHARE_KEY),
                    Add(profitPerRuningVaultShareToBeAdd,
                        getProfitPerRunningVaultShare(currentRound)))
            # update real time running vault
            Delete(GetContext(), realTimeRunVaultKey)
            Notify(["endCurrentRound", currentRound])
            return True
    else:
        # update total ong amount
        Put(GetContext(), TOTAL_ONG_KEY, Add(totalOngAmount, ongAmount))

        # update profit per investment for bankers
        runVaultLeft = getRunningVault(currentRound)
        if runVaultLeft > 0:
            profitPerRunNingVaultShareToBeAdd = Div(
                Mul(ongAmount, MagnitudeForProfitPerSth), runVaultLeft)
            Put(
                GetContext(),
                concatKey(concatKey(ROUND_PREFIX, currentRound),
                          PROFIT_PER_RUNNING_VAULT_SHARE_KEY),
                Add(profitPerRunNingVaultShareToBeAdd,
                    getProfitPerRunningVaultShare(currentRound)))

    Notify([
        "bet", currentRound, account, number, theNumber, ongAmount, payOutToWin
    ])
    return True
def fillPaper(account, guessNumberList):
    """
    :param account:
    :param guessNumberList: can be a list of numbers
    :return:
    """
    RequireWitness(account)

    currentRound = getCurrentRound()

    Require(getGameStatus(currentRound) == STATUS_ON)

    # to prevent hack from other contract
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    Require(callerHash == entryHash)
    # Require(entryHash == ContractAddress)

    guessNumberLen = len(guessNumberList)

    Require(guessNumberLen >= 1)

    currentPaperBalance = getPaperBalance(account)

    # make sure his balance is greater or equal to guessNumberList length
    Require(currentPaperBalance >= guessNumberLen)

    numberListKey = concatKey(concatKey(ROUND_PREFIX, currentRound), FILLED_NUMBER_LIST_KEY)
    numberListInfo = Get(GetContext(), numberListKey)
    numberList = []
    if numberListInfo:
        numberList = Deserialize(numberListInfo)

    for guessNumber in guessNumberList:

        # Require is need to raise exception
        Require(guessNumber < 100)
        Require(guessNumber >= 0)

        numberPlayersListKey = concatKey(concatKey(ROUND_PREFIX, currentRound), concatKey(FILLED_NUMBER_KEY, guessNumber))
        numberPlayersListInfo = Get(GetContext(), numberPlayersListKey)

        numberPlayersList = []
        if numberPlayersListInfo:
            numberPlayersList = Deserialize(numberPlayersListInfo)

            # make sure account has NOT filled the number before in this round
            for player in numberPlayersList:
                Require(player != account)
        else:
            numberList.append(guessNumber)

        # add account to the players list that filled the number in this round
        numberPlayersList.append(account)

        # Store the numberPlayers List
        numberPlayersListInfo = Serialize(numberPlayersList)
        Put(GetContext(), numberPlayersListKey, numberPlayersListInfo)
    # Store the numberList
    numberListInfo = Serialize(numberList)
    Put(GetContext(), numberListKey, numberListInfo)

    # update dividend
    updateDividendBalance(account)

    # update the paper balance of account  -- destroy the filled papers
    Put(GetContext(), concatKey(PAPER_BALANCE_PREFIX, account), Sub(currentPaperBalance, guessNumberLen))

    # update total paper amount
    Put(GetContext(), TOTAL_PAPER_KEY, Sub(getTotalPaper(), guessNumberLen))

    # update the filled paper balance of account in current round
    key1 = concatKey(ROUND_PREFIX, currentRound)
    key2 = concatKey(FILLED_PAPER_BALANCE_PREFIX, account)
    key = concatKey(key1, key2)
    Put(GetContext(), key, Add(guessNumberLen, getFilledPaperBalance(account, currentRound)))

    # update the filled paper amount in current round
    key = concatKey(concatKey(ROUND_PREFIX, currentRound), FILLED_PAPER_AMOUNT)
    Put(GetContext(), key, Add(guessNumberLen, getFilledPaperAmount(currentRound)))

    Notify(["fillPaper", account, guessNumberList, GetTime()])

    return True
Exemple #16
0
def IsFromContract():
    callerHash = GetCallingScriptHash()
    entryHash = GetEntryScriptHash()
    if callerHash != entryHash:
        return True
    return False