Example #1
0
def add_certification(address, caller_address, content):
    """Writes to the blockchain something about the given address

    returns: success message
    """
    ctx = GetContext()
    current_data = Get(ctx, address)
    new_entry = concat(caller_address, content)
    new_data = []

    if not current_data:
        new_data.append(new_entry)

    else:
        current_data = deserialize_bytearray(current_data)
        current_data.append(new_entry)
        new_data = current_data

    final_data = serialize_array(new_data)
    Put(ctx, address, final_data)
    Log('New certification added.')
    return 'Success: New certification added'
Example #2
0
def PlaceNewBid(args):
    owner = args[0]
    name = args[1]
    date = args[2]
    ad_url = args[3]
    image_urls = args[4]

    context = GetContext()
    time = GetTime(context)
    attachments = get_asset_attachments()

    user = attachments[1]
    bid_amount = attachments[3]

    publication_key = validatePublicationAuction(context, args)
    if not publication_key:
        return [False, 'Invalid auction params']

    if time >= date:
        print('Auction has finished')
        return [False, 'Auction finished']

    if bid_amount <= 0:
        print('No NeoGAS has been attached')
        return [False, 'No GAS attached']

    has_claimed = False

    new_bid = [user, bid_amount, ad_url, image_urls, time]
    new_auction = [user, bid_amount, has_claimed]

    auction_key = concat(publication_key, sha1(date))
    bids_key = concat(auction_key, 'bids')
    auction = Get(context, auction_key)

    # If no previous bids automatically accept and store current bid
    if not auction:
        Put(context, auction_key, Serialize(new_auction))
        Put(context, bids_key, Serialize([new_bid]))

        return [True, '']

    auction = Deserialize(auction)

    previous_user = auction[0]
    previous_bid = auction[1]

    if previous_bid >= bid_amount:
        print('Must bid more than the current best bid')
        OnRefund(user, bid_amount)
        return [False, 'Must bid more than current best bid']

    bids = Get(context, bids_key)
    bids = Deserialize(bids)

    bids.append(new_bid)

    Put(context, auction_key, Serialize(new_auction))
    Put(context, bids_key, Serialize(bids))

    # Re-credit funds to previous bidder
    AddFunds(context, previous_user, previous_bid)

    return [True, '']
Example #3
0
def CreatePublication(args):
    sender = args[0]
    name = args[1]
    url = args[2]
    category = args[3]

    if not CheckWitness(sender):
        print('Account owner must be sender')
        return [False, 'Account owner must be sender']

    # Add char limit to prevent big storage costs
    if (len(name) > 255 or len(url) > 255 or len(category) > 255):
        print('Args must be less than 255 chars')
        return [False, 'Arguments must be less than 255 chars']

    context = GetContext()

    publications_key = concat('publications', sender)  # Publications by user
    publication_key = concat(
        publications_key,
        sha1(name))  # Publication details - sha1 to prevent malicious input
    new_publications_key = 'new_publications'  # List of new publications for front page view

    publications = Get(context, publications_key)
    publication = Get(context, publication_key)
    new_publications = Get(context, new_publications_key)

    # If publication already exists check if it is active/deleted
    if publication:
        publication = Deserialize(publication)
        if publication[5]:
            print('Publication name currently active')
            return [False, 'Active publication name']

    # Check if user has publications already
    if publications:
        publications = Deserialize(publications)
    else:
        publications = []

    # Check if there are publications in the all_publications view
    if new_publications:
        new_publications = Deserialize(new_publications)
    else:
        new_publications = []

    first_date = getWarpedTime(context) + (
        SECONDS_IN_DAY -
        getWarpedTime(context) % SECONDS_IN_DAY) + SECONDS_IN_HOUR * -TIMEZONE
    is_active = True

    new_publication = [sender, name, url, category, first_date, is_active]
    publications.append(name)
    new_publications.append([sender, name])

    # Shift new publication list to the left
    if len(new_publications) > 5:
        new_publications = [
            new_publications[1], new_publications[2], new_publications[3],
            new_publications[4], new_publications[5]
        ]

    Put(context, publication_key, Serialize(new_publication))
    Put(context, publications_key, Serialize(publications))
    Put(context, new_publications_key, Serialize(new_publications))

    return [True, '']
Example #4
0
def Main(operation, args):
    """Entry point to the program

    :param str operation: The name of the operation to perform
    :param list args: A list of arguments along with the operation
    :return: The result of the operation
    :rtype: bytearray

    Token operations:
    - allowance(token_id): returns approved third-party spender of a
        token
    - approve(token_receiver, token_id, revoke): approve third party
        to spend a token
    - balanceOf(owner): returns owner's current total tokens owned
    - name(): returns name of token
    - decimals(): returns token decimal precision
    - ownerOf(token_id): returns the owner of the specified token.
    - properties(token_id): returns a token's read-only data
    - rwProperties(token_id): returns a token's read/write data
    - supportedStandards(): returns a list of supported standards
        {"NEP-10"}
    - symbol(): returns token symbol
    - token(token_id): returns a dictionary where token, property,
        and uri keys map to the corresponding data for the given
        `token_id`
    - tokensOfOwner(owner, starting_index): returns a dictionary that
        contains less than or equal to ten of the tokens owned by
        the specified address starting at the `starting_index`.
    - totalSupply(): Returns the total token supply deployed in the
        system.
    - transfer(to, token_id, extra_arg): transfers a token
    - transferFrom(spender, from, to, token_id): allows a third party
        to execute a pre-approved transfer
    - uri(token_id): Returns a distinct Uniform Resource Identifier
        (URI) for a given asset.
        The URI data of a token supplies a reference to get more
        information about a specific token or its data.

    TOKEN_CONTRACT_OWNER operations:
        - mintToken(owner, properties, URI, extra_arg): create a new
            NFT token with the specified properties and URI and send it
            to the specified owner
        - modifyURI(token_id, token_data): modify specified token's
            URI data

        setters:
        - setName(name): sets the name of the token
        - setSymbol(symbol): sets the token's symbol
        - setSupportedStandards(supported_standards): sets the
            supported standards, 'NEP-10' is always the first element
            in the array
    """
    # The trigger determines whether this smart contract is being run
    # in 'verification' mode or 'application'
    trigger = GetTrigger()

    # 'Verification' mode is used when trying to spend assets
    # (eg NEO, Gas) on behalf of this contract's address
    if trigger == Verification():

        # if the script that sent this is the owner, we allow the spend
        if CheckWitness(TOKEN_CONTRACT_OWNER):
            return True

    elif trigger == Application():

        # Need to get this at the top level
        caller = GetCallingScriptHash()
        ctx = GetContext()

        if operation == 'name':
            name = Get(ctx, 'name')
            if name:
                return name
            else:
                return TOKEN_NAME

        elif operation == 'symbol':
            symbol = Get(ctx, 'symbol')
            if symbol:
                return symbol
            else:
                return TOKEN_SYMBOL

        elif operation == 'supportedStandards':
            supported_standards = Get(ctx, 'supportedStandards')
            if supported_standards:
                return supported_standards
            else:
                return Serialize(['NEP-10'])

        elif operation == 'totalSupply':
            return Get(ctx, TOKEN_CIRC_KEY)

        elif operation == 'allowance':
            assert len(args) == 1, ARG_ERROR
            ownership = safe_deserialize(
                Get(ctx, concat('ownership/', args[0])))
            assert ownership, TOKEN_DNE_ERROR
            # don't fault here in case a calling contract is just checking allowance value
            if not has_key(ownership, 'approved'): return False
            if len(ownership['approved']) != 40: return False
            return ownership['approved']

        elif operation == 'balanceOf':
            assert len(args) == 1, ARG_ERROR
            assert len(args[0]) == 20, INVALID_ADDRESS_ERROR
            token_iter = Find(ctx, args[0])
            count = 0
            while token_iter.next():
                count += 1
            return count

        elif operation == 'ownerOf':
            assert len(args) == 1, ARG_ERROR
            ownership = safe_deserialize(
                Get(ctx, concat('ownership/', args[0])))
            assert ownership, TOKEN_DNE_ERROR
            assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR
            assert len(ownership['owner']) == 20, TOKEN_DNE_ERROR
            return ownership['owner']

        elif operation == 'properties':
            assert len(args) == 1, ARG_ERROR
            return get_properties(ctx, args[0])

        elif operation == 'rwProperties':
            assert len(args) == 1, ARG_ERROR
            return get_rw_properties(ctx, args[0])

        elif operation == 'token':
            assert len(args) == 1, ARG_ERROR
            token = Get(ctx, concat('token/', args[0]))
            assert token, TOKEN_DNE_ERROR
            return token

        elif operation == 'tokensOfOwner':
            assert len(args) == 2, ARG_ERROR
            tokens_of_owner = do_tokens_of_owner(ctx, args[0], args[1])
            assert tokens_of_owner, 'address has no tokens'
            return Serialize(tokens_of_owner)

        elif operation == 'uri':
            assert len(args) == 1, ARG_ERROR
            token = safe_deserialize(Get(ctx, concat('token/', args[0])))
            assert token, TOKEN_DNE_ERROR
            assert has_key(token, 'uri'), TOKEN_DNE_ERROR
            return token['uri']

        elif operation == 'decimals':
            return TOKEN_DECIMALS

        #
        # User RW operations
        #

        if operation == 'approve':
            # args: from, spender, id, revoke
            # (NFT needs a fourth argument to revoke approval)
            assert len(args) > 2, ARG_ERROR
            assert args[2], TOKEN_DNE_ERROR
            return do_approve(ctx, caller, args)

        elif operation == 'transfer':
            assert len(args) > 1, ARG_ERROR
            return do_transfer(ctx, caller, args)

        elif operation == 'transferFrom':

            assert len(args) > 2, ARG_ERROR
            if len(args) == 3:
                # Nash-style (from, to, amount/id) transferFrom that can
                # be invoked only by whitelisted DEX to initiate a
                # pre-approved transfer

                return nash_do_transfer_from(ctx, caller, args)
            else:
                # Moonlight-style (spender, from, to, amount/id)
                # transfer where an authenticated spender/originator is
                # the only one who can initiate a transfer but can send
                # to an arbitrary third party (or themselves)

                return do_transfer_from(ctx, caller, args)

        #
        # dApp operations
        #
        if operation == 'setRWProperties':
            # args: token id, rwdata
            assert CheckWitness(DAPP_ADMIN), PERMISSION_ERROR
            assert len(args) == 2, ARG_ERROR
            return set_rw_properties(ctx, args[0], args[1])

        # Administrative operations
        if CheckWitness(TOKEN_CONTRACT_OWNER):
            if operation == 'mintToken':
                assert len(args) > 3, ARG_ERROR
                return do_mint_token(ctx, args)

            elif operation == 'modifyURI':
                assert len(args) == 2, ARG_ERROR
                return do_modify_uri(ctx, args)

            elif operation == 'setName':
                assert len(args) == 1, ARG_ERROR
                return do_set_config(ctx, 'name', args[0])

            elif operation == 'setSymbol':
                assert len(args) == 1, ARG_ERROR
                return do_set_config(ctx, 'symbol', args[0])

            elif operation == 'setSupportedStandards':
                assert len(args) >= 1, ARG_ERROR
                supported_standards = ['NEP-10']
                for arg in args:
                    supported_standards.append(arg)
                return do_set_config(ctx, 'supportedStandards',
                                     Serialize(supported_standards))

        AssertionError('unknown operation')
    return False
Example #5
0
def Main(operation, args):
    """
    Main definition for the smart contracts
    :param operation: the operation to be performed
    :type operation: str
    :param args: list of arguments.
        args[0]  is always sender script hash
        args[1]  is Poll Data or Poll Index
        args[2]+ eligible addresses
    :param type: str
    :return:
        byterarray: The result of the operation
    """
    user_address = args[0]  #Always needed

    if operation == 'GetPublicAll':
        publicPolls = Get(GetContext(), "public")

        if publicPolls is None:
            return "There are no public polls"
        else:
            publicPolls = Deserialize(publicPolls)

            publicPollsObj = []

            for pollID in publicPolls:
                pollItem = []
                pollItem.append(pollID)

                Log(pollID)

                vote_list = concat(pollID, ".vote_list")
                vl = Get(GetContext(), vote_list)
                if vl is None:
                    pollItem.append(len(vl))
                else:
                    pollItem.append(len(Deserialize(vl)))

                vote_key = concat(pollID, ".")
                vote_key = concat(vote_key, user_address)
                vote = Get(GetContext(), vote_key)
                if vote is None:
                    pollItem.append("false")
                else:
                    pollItem.append("true")

                publicPollsObj.append(pollItem)

            return publicPollsObj

    if operation == 'GetPollById':
        #input parameters
        pollID = args[1]
        poll = Get(GetContext(), pollID)

        if poll is None:
            return "Poll with given ID doesn't exist"
        else:
            return Deserialize(poll)

    if operation == 'GetAssignedPolls':
        user_key = concat(user_address, ".assigned")

        pollsAssigned = Get(GetContext(), user_key)

        if pollsAssigned is None:
            return "There are no private polls assigned to the current user"
        else:
            pollsAssigned = Deserialize(pollsAssigned)

            pollsObj = []

            for pollID in pollsAssigned:
                pollItem = []
                pollItem.append(pollID)

                vote_list = concat(pollID, ".vote_list")
                vl = Get(GetContext(), vote_list)
                if vl is None:
                    pollItem.append(len(vl))
                else:
                    pollItem.append(len(Deserialize(vl)))

                vote_key = concat(pollID, ".")
                vote_key = concat(vote_key, user_address)
                vote = Get(GetContext(), vote_key)
                if vote is None:
                    pollItem.append("false")
                else:
                    pollItem.append("true")

                pollsObj.append(pollItem)

            return pollsObj

    if operation == 'GetCreatedPolls':
        user_key = concat(user_address, ".created")

        pollsCreated = Get(GetContext(), user_key)

        if pollsCreated is None:
            return "There are no private polls created by current user"
        else:
            pollsCreated = Deserialize(pollsCreated)

            pollsObj = []

            for pollID in pollsCreated:
                pollItem = []
                pollItem.append(pollID)

                vote_list = concat(pollID, ".vote_list")
                vl = Get(GetContext(), vote_list)
                if vl is None:
                    pollItem.append(len(vl))
                else:
                    pollItem.append(len(Deserialize(vl)))

                vote_key = concat(pollID, ".")
                vote_key = concat(vote_key, user_address)
                vote = Get(GetContext(), vote_key)
                if vote is None:
                    pollItem.append("false")
                else:
                    pollItem.append("true")

                pollsObj.append(pollItem)

            return pollsObj

    if operation == 'GetAssignedByAddress':
        user_key = concat(args[1], ".assigned")

        pollsAssigned = Get(GetContext(), user_key)

        if pollsAssigned is None:
            return "There are no private polls assigned to this address"
        else:
            return Deserialize(pollsAssigned)

    if operation == 'GetPollCount':
        pollCount = Get(GetContext(), "pollCount")

        if pollCount is None:
            return "Contract does not contain any poll"
        else:
            return Deserialize(pollCount)

    if operation == 'GetVoteListById':
        pollID = args[1]

        vote_list = concat(pollID, ".vote_list")
        vl = Get(GetContext(), vote_list)
        if vl is None:
            return "This poll has 0 participants so far"
        else:
            return Deserialize(vl)

    if operation == 'CheckVoteByIdAndAddress':
        #input parameters
        pollID = args[1]
        target_address = args[2]

        vote_key = concat(pollID, ".")
        vote_key = concat(vote_key, target_address)

        vote = Get(GetContext(), vote_key)
        if vote is None:
            return "Current user has not participated in this poll"
        else:
            return Deserialize(vote)

    if operation == 'GetOptionResults':
        pollID = args[1]
        optionID = args[2]

        option_key = concat(pollID, ".")
        option_key = concat(option_key, optionID)

        option_count = Get(GetContext(), option_key)
        if option_count is None:
            return len(option_count)
        else:
            Log(option_count)
            return Deserialize(option_count)

    if operation == 'RegisterVote':
        data = args[1]
        pollID = args[2]

        vote_key = concat(pollID, ".")
        vote_key = concat(vote_key, user_address)

        vote = Get(GetContext(), vote_key)
        if vote is None:
            Put(GetContext(), vote_key, Serialize(args))

            vote_list = concat(pollID, ".vote_list")
            vl = Get(GetContext(), vote_list)
            if vl is None:
                vl = []
                vl.append(user_address)
                Put(GetContext(), vote_list, Serialize(vl))
            else:
                vl = Deserialize(vl)
                vl.append(user_address)
                Put(GetContext(), vote_list, Serialize(vl))

        else:
            return "User has already participated in this vote"

        if len(args) > 2:
            iterator = 0
            for argument in args:
                if iterator > 2:
                    option_id = argument
                    option_key = concat(pollID, ".")
                    option_key = concat(option_key, option_id)

                    option_count = Get(GetContext(), option_key)
                    if option_count is None:
                        option_count = 1
                        Put(GetContext(), option_key, Serialize(option_count))
                    else:
                        option_count = Deserialize(option_count)
                        option_count += 1
                        Put(GetContext(), option_key, Serialize(option_count))
                iterator = iterator + 1

        return "Vote Successful"

    if operation == 'RegisterPoll':
        #input parameters
        data = args[1]
        poll_name = args[2]
        address_list = args[3]

        #Save latest poll ID
        pollID = Get(GetContext(), "pollCount")
        poll_key = poll_name

        if pollID is None:
            pollIDInt = 1
            pollID = Serialize(pollIDInt)
            Put(GetContext(), "pollCount", pollID)
        else:
            pollIDInt = Deserialize(pollID)
            pollIDInt += 1
            pollID = Serialize(pollIDInt)
            Put(GetContext(), "pollCount", pollID)

        #Save poll to corresponding addresses
        if address_list is None:
            publicPolls = Get(GetContext(), "public")
            if publicPolls is None:
                publicPolls = []
                publicPolls.append(poll_key)
                Put(GetContext(), "public", Serialize(publicPolls))
            else:
                publicPolls = Deserialize(publicPolls)
                publicPolls.append(poll_key)
                Put(GetContext(), "public", Serialize(publicPolls))
        else:
            iterator = 0
            for argument in args:
                if iterator > 2:
                    target_address = argument
                    user_key = concat(target_address, ".assigned")

                    pollsAssigned = Get(GetContext(), user_key)
                    if pollsAssigned is None:
                        pollsAssigned = []
                        pollsAssigned.append(poll_key)
                        Put(GetContext(), user_key, Serialize(pollsAssigned))
                    else:
                        pollsAssigned = Deserialize(pollsAssigned)
                        pollsAssigned.append(poll_key)
                        Put(GetContext(), user_key, Serialize(pollsAssigned))
                iterator = iterator + 1

        owner_key = concat(user_address, ".created")

        pollsCreated = Get(GetContext(), owner_key)
        if pollsCreated is None:
            pollsCreated = []
            pollsCreated.append(poll_key)
            Put(GetContext(), owner_key, Serialize(pollsCreated))
        else:
            pollsCreated = Deserialize(pollsCreated)
            pollsCreated.append(poll_key)
            Put(GetContext(), owner_key, Serialize(pollsCreated))

        Put(GetContext(), poll_key, Serialize(args))
        return poll_key

    # Everything after this requires authorization
    authorized = CheckWitness(user_address)
    if not authorized:
        Log("Not Authorized")
        return False
    Log("Authorized")

    return False
def Main(operation, args):
    """Entry point to the program

    :param str operation: The name of the operation to perform
    :param list args: A list of arguments along with the operation
    :return: The result of the operation
    :rtype: bytearray

    Token operations:
    - allowance(token_id): returns approved third-party spender of a
        token
    - approve(token_receiver, token_id, revoke): approve third party
        to spend a token
    - balanceOf(owner): returns owner's current total tokens owned
    - name(): returns name of token
    - ownerOf(token_id): returns the owner of the specified token.
    - properties(token_id): returns a token's read-only data
    - supportedStandards(): returns a list of supported standards
        {"NEP-10"}
    - symbol(): returns token symbol
    - tokenData(token_id): returns a dictionary where token, property,
        and uri keys map to the corresponding data for the given
        `token_id`
    - tokensDataOfOwner(owner, starting_index): returns a dictionary
        that contains less than or equal to five of the tokens (where
        token, properties, and uri keys map to their corresponding data
        for each token id) owned by the specified address starting at
        the `starting_index`.
    - tokensOfOwner(owner, starting_index): returns a dictionary that
        contains less than or equal to ten of the tokens owned by
        the specified address starting at the `starting_index`.
    - totalSupply(): Returns the total token supply deployed in the
        system.
    - transfer(to, token_id, extra_arg): transfers a token
    - transferFrom(from, to, token_id, extra_arg): allows a third party
        to execute an approved transfer
    - uri(token_id): Returns a distinct Uniform Resource Identifier
        (URI) for a given asset.
        The URI data of a token supplies a reference to get more
        information about a specific token or its data.

    TOKEN_CONTRACT_OWNER operations:
        - mintToken(owner, properties, URI, extra_arg): create a new
            NFT token with the specified properties and URI and send it
            to the specified owner
        - modifyURI(token_id, token_data): modify specified token's
            URI data

        setters:
        - setName(name): sets the name of the token
        - setSymbol(symbol): sets the token's symbol
        - setSupportedStandards(supported_standards): sets the
            supported standards, 'NEP-10' is always the first element
            in the array
    """
    # The trigger determines whether this smart contract is being run
    # in 'verification' mode or 'application'
    trigger = GetTrigger()

    # 'Verification' mode is used when trying to spend assets
    # (eg NEO, Gas) on behalf of this contract's address
    if trigger == Verification():

        # if the script that sent this is the owner, we allow the spend
        if CheckWitness(TOKEN_CONTRACT_OWNER):
            return True

    elif trigger == Application():

        ctx = GetContext()

        if operation == 'name':
            name = Get(ctx, 'name')
            if name:
                return name
            else:
                return TOKEN_NAME

        elif operation == 'symbol':
            symbol = Get(ctx, 'symbol')
            if symbol:
                return symbol
            else:
                return TOKEN_SYMBOL

        elif operation == 'supportedStandards':
            supported_standards = Get(ctx, 'supportedStandards')
            if supported_standards:
                return supported_standards
            else:
                return Serialize(['NEP-10'])

        elif operation == 'totalSupply':
            return Get(ctx, TOKEN_CIRC_KEY)

        if operation == 'allowance':
            if len(args) == 1:
                return Get(ctx, concat('approved/', args[0]))

            Notify(ARG_ERROR)
            return False

        elif operation == 'approve':
            if len(args) == 3:
                # GetCallingScriptHash() can't be done within the
                # function because the calling script hash changes
                # depending on where the function is called
                return do_approve(ctx, GetCallingScriptHash(), args[0],
                                  args[1], args[2])

            Notify(ARG_ERROR)
            return False

        elif operation == 'balanceOf':
            if len(args) == 1:
                if len(args[0]) == 20:
                    return Get(ctx, args[0])

                Notify(INVALID_ADDRESS_ERROR)
                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'ownerOf':
            if len(args) == 1:
                t_owner = Get(ctx, args[0])
                if len(t_owner) == 20:
                    return t_owner

                Notify(TOKEN_DNE_ERROR)
                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'properties':
            if len(args) == 1:
                token_properties = Get(ctx, concat('properties/', args[0]))
                if token_properties:
                    return token_properties

                Notify(TOKEN_DNE_ERROR)
                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'tokenData':
            if len(args) == 1:
                # check to make sure the token exists
                if len(Get(ctx, args[0])) == 20:
                    return Serialize(do_token_data(ctx, args[0]))

                Notify(TOKEN_DNE_ERROR)
                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'tokensDataOfOwner':
            if len(args) == 2:
                tokens_data_of_owner = do_tokens_data_of_owner(
                    ctx, args[0], args[1])
                if tokens_data_of_owner:
                    return Serialize(tokens_data_of_owner)

                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'tokensOfOwner':
            if len(args) == 2:
                tokens_of_owner = do_tokens_of_owner(ctx, args[0], args[1])
                if tokens_of_owner:
                    return Serialize(tokens_of_owner)

                return False

            Notify(ARG_ERROR)
            return False

        elif operation == 'transfer':
            if len(args) >= 2:
                # GetCallingScriptHash() can't be done within the
                # function because the calling script hash changes
                # depending on where the function is called
                return do_transfer(ctx, GetCallingScriptHash(), args)

            Notify(ARG_ERROR)
            return False

        elif operation == 'transferFrom':
            if len(args) >= 3:
                return do_transfer_from(ctx, args)

            Notify(ARG_ERROR)
            return False

        elif operation == 'uri':
            if len(args) == 1:
                token_uri = Get(ctx, concat('uri/', args[0]))
                if token_uri:
                    return token_uri

                Notify(TOKEN_DNE_ERROR)
                return False

            Notify(ARG_ERROR)
            return False

        # Administrative operations
        if CheckWitness(TOKEN_CONTRACT_OWNER):
            if operation == 'mintToken':
                if len(args) >= 3:
                    return do_mint_token(ctx, args)

                Notify(ARG_ERROR)
                return False

            elif operation == 'modifyURI':
                if len(args) == 2:
                    return do_modify_uri(ctx, args[0], args[1])

                Notify(ARG_ERROR)
                return False

            elif operation == 'setName':
                if len(args) == 1:
                    return do_set_config(ctx, 'name', args[0])

                Notify(ARG_ERROR)
                return False

            elif operation == 'setSymbol':
                if len(args) == 1:
                    return do_set_config(ctx, 'symbol', args[0])

                Notify(ARG_ERROR)
                return False

            elif operation == 'setSupportedStandards':
                if len(args) >= 1:
                    supported_standards = ['NEP-10']
                    for arg in args:
                        supported_standards.append(arg)

                    return do_set_config(ctx, 'supportedStandards',
                                         Serialize(supported_standards))

                Notify(ARG_ERROR)
                return False

        else:
            Notify(PERMISSION_ERROR)
            return False

        Notify('unknown operation')

    return False