Exemplo n.º 1
0
def remove_liquidity(liquidity: int, amount_token_a_min: int,
                     amount_token_b_min: int,
                     user_address: UInt160) -> List[int]:
    """
    Remove liquidity from the pool, burning the AMM token in the process and giving token_a and token_b back to the user.

    :param liquidity: how much liquidity will be removed from the liquidity pool
    :type liquidity: int
    :param amount_token_a_min: minimum amount of token_a that will be transferred to the user
    :type amount_token_a_min: int
    :param amount_token_b_min: minimum amount of token_b that will be transferred to the user
    :type amount_token_b_min: int
    :param user_address: the user's address
    :type user_address: UInt160

    :return: at index 0 and 1, the amount of token_a and token_b tokens that were transferred, respectively
    :rtype: list

    :raise AssertionError: raised if the user doesn't have enough liquidity, or if the amount of token_a or token_b received after
    burning the liquidity is not greater than the minimum amount that the user wanted, or if the one calling this
    function is not the user_address
    """
    # this verification exists thanks to a limitation in the TestEngine, it's returning None when using calling_script_hash
    # using just `user_address = calling_script hash` should be enough
    if runtime.calling_script_hash is not None:  # TODO: remove the verification when the TestEngine starts sending a calling script hash
        user_address = runtime.calling_script_hash
    else:
        assert runtime.check_witness(user_address)

    assert runtime.check_witness(user_address)
    assert liquidity <= balance_of(user_address)
    amount = burn(liquidity, user_address)
    # Verify if the amount of token_a and token_b are equal or greater than the minimum amount
    assert amount[0] >= amount_token_a_min and amount[1] >= amount_token_b_min
    return amount
Exemplo n.º 2
0
def swap_tokens(amount_in: int, amount_out_min: int, token_in: UInt160, user_address: UInt160) -> int:
    """
    Swaps two tokens with a small fee in the process.

    :param amount_in: the amount of tokens that the user is trying to swap
    :type amount_in: int
    :param amount_out_min: the minimum amount of tokens that the user wants to receive
    :type amount_out_min: int
    :param token_in: the address of the token that the user is trying to use in the swap
    :type token_in: UInt160
    :param user_address: the user's address
    :type user_address: UInt160

    :return: the amount of tokens that the user received from the swap
    :rtype: int
    """
    # this verification exists thanks to a limitation in the TestEngine, it's returning None when using calling_script_hash
    # using just `user_address = calling_script hash` should be enough
    if calling_script_hash is not None:     # TODO: remove the verification when the TestEngine starts sending a calling script hash
        user_address = calling_script_hash
    else:
        assert check_witness(user_address)

    assert check_witness(user_address)
    assert token_in == UInt160(get(TOKEN_A)) or token_in == UInt160(get(TOKEN_B))

    # Verifies if the user is trying to swap token_a or token_b and set the variables accordingly
    if token_in == UInt160(get(TOKEN_A)):
        reserve_token_in = get(SUPPLY_KEY + TOKEN_A).to_int()
        reserve_token_out = get(SUPPLY_KEY + TOKEN_B).to_int()
        amount_token_a_in = amount_in
        amount_token_b_in = 0
    else:
        reserve_token_in = get(SUPPLY_KEY + TOKEN_B).to_int()
        reserve_token_out = get(SUPPLY_KEY + TOKEN_A).to_int()
        amount_token_a_in = 0
        amount_token_b_in = amount_in

    # Calculates the amount of tokens the user will receive
    amount_in_fee = amount_in * (1000 - FEE)
    amount_out = amount_in_fee * reserve_token_out // (reserve_token_in * 1000 + amount_in_fee)
    assert amount_out >= amount_out_min

    # Checks if the user allowed enough tokens
    amount_allowed = call_contract(token_in, 'allowance', [user_address, executing_script_hash])
    if isinstance(amount_allowed, int):
        assert amount_allowed >= amount_in
    else:
        abort()
    call_contract(token_in, 'transfer_from', [executing_script_hash, user_address, executing_script_hash, amount_in, None])

    if amount_token_a_in != 0:
        swap(0, amount_out, user_address)
    else:
        swap(amount_out, 0, user_address)

    return amount_out
Exemplo n.º 3
0
def getFeesMap() -> Iterator:
    """
    How many fees of each kind of token can be collected
    :return: collateral_token: amount_of_fees.to_bytes()
    """
    administrator = get(ADMINISTRATOR_KEY)
    if not (check_witness(administrator)
            or calling_script_hash == administrator):
        fee_receiver = get(
            FEE_RECEIVER_KEY
        )  # if not admin, get fee_receiver. This saves GAS for executing this API
        assert check_witness(
            fee_receiver) or calling_script_hash == fee_receiver
    return find(b'feesMap')
Exemplo n.º 4
0
def update_sc(nef_file: bytes, manifest: bytes, data: Any = None):
    """
    Updates the smart contract. In this example there is a bugged method, so, the smart contract will be updated to fix
    the bug.
    """
    if check_witness(OWNER):
        ContractManagement.update(nef_file, manifest, data)
Exemplo n.º 5
0
def approve(originator: UInt160, to_address: UInt160, amount: int) -> bool:
    """
    Approves the to account to transfer amount tokens from the originator account.

    :param originator: the address that have the tokens
    :type originator: UInt160
    :param to_address: the address that is authorized to use the tokens
    :type to_address: UInt160
    :param amount: the amount of NEP17 tokens to transfer
    :type amount: int

    :return: whether the approval was successful
    :raise AssertionError: raised if `originator` or `to_address` length is not 20 or if `amount` if less than zero.
    """
    assert len(originator) == 20 and len(to_address) == 20
    assert amount >= 0

    if not runtime.check_witness(originator):
        return False

    if originator == to_address:
        return False

    if not is_valid_address(originator) or not is_valid_address(to_address):
        # one of the address doesn't passed the kyc yet
        return False

    if balance_of(originator) < amount:
        return False

    storage.put(TRANSFER_ALLOWANCE_PREFIX + originator + to_address, amount)
    return True
Exemplo n.º 6
0
def cancel_pool(pool_id: UInt256):
    creator_on_storage = get(POOL_OWNER_KEY + pool_id)

    if len(creator_on_storage) == 0:
        raise Exception("Pool doesn't exist.")

    creator = UInt160(creator_on_storage)
    if not check_witness(creator):
        raise Exception('No authorization.')
    if len(get(POOL_RESULT_KEY + pool_id)) > 0:
        raise Exception('Pool is finished already')

    executing_contract = executing_script_hash

    # refund players
    bets_key_prefix = POOL_BET_KEY + pool_id
    bet = find(bets_key_prefix)
    while bet.next():
        result_pair: List[bytes] = bet.value
        storage_key = result_pair[0]

        account = UInt160(storage_key[len(bets_key_prefix):])
        transfer_gas(executing_contract, account, PRICE_IN_GAS)

    # set result
    put(POOL_RESULT_KEY + pool_id, serialize('Cancelled by owner'))
Exemplo n.º 7
0
def deploy(administrator: UInt160) -> bool:
    """
    administrating access is mostly related to flashLoan
    """
    assert check_witness(administrator) or calling_script_hash == administrator
    if get(DEPLOYED_KEY) == b'':  # not deployed
        assert get(ADMINISTRATOR_KEY) == b''
        put(ADMINISTRATOR_KEY, administrator)
        put(FEE_RECEIVER_KEY, administrator)
        put(DEPLOYED_KEY, 1)
    else:
        original_administrator = get(ADMINISTRATOR_KEY)
        assert check_witness(original_administrator
                             ) or calling_script_hash == original_administrator
        put(ADMINISTRATOR_KEY, administrator)
    return True
Exemplo n.º 8
0
def mint(account: UInt160, meta: bytes, lockedContent: bytes, royalties: bytes,
         data: Any) -> bytes:
    """
    Mint new token.

    :param account: the address of the account that is minting token
    :type account: UInt160
    :param meta: the metadata to use for this token
    :type meta: bytes
    :param lockedContent: the lock content to use for this token
    :type lockedContent: bytes
    :param royalties: the royalties to use for this token
    :type royalties: bytes
    :param data: whatever data is pertinent to the mint method
    :type data: Any
    :return: tokenId of the token minted
    :raise AssertionError: raised if mint fee is less than than 0 or if the account does not have enough to pay for it or if the contract is paused or if check witness fails.
    """
    assert not isPaused(), "GhostMarket contract is currently paused"

    fee = get_mint_fee()
    assert fee > 0, "Mint fee can't be < 0"
    assert check_witness(account), "Invalid witness"

    if fee > 0:
        # TODO use calling_script_hash instead of account
        success: bool = call_contract(
            GAS, 'transfer', [account, executing_script_hash, fee, None])
        assert success, "Fee payment failed!"

    return internal_mint(account, meta, lockedContent, royalties, data)
Exemplo n.º 9
0
def is_administrator() -> bool:
    """
    Validates if the invoker has administrative rights

    :return: whether the contract's invoker is an administrator
    """
    return runtime.check_witness(TOKEN_OWNER)
Exemplo n.º 10
0
def burn(account: UInt160, amount: int):
    """
    Burns zNEO tokens.

    :param account: the address of the account that is pulling out cryptocurrency of this contract
    :type account: UInt160
    :param amount: the amount of gas to be refunded
    :type amount: int
    :raise AssertionError: raised if `account` length is not 20, amount is less than than 0 or the account doesn't have
    enough zNEO to burn
    """
    assert len(account) == 20
    assert amount >= 0
    if check_witness(account):
        if amount != 0:
            current_total_supply = totalSupply()
            account_balance = balanceOf(account)

            assert account_balance >= amount

            put(SUPPLY_KEY, current_total_supply - amount)

            if account_balance == amount:
                delete(account)
            else:
                put(account, account_balance - amount)

            on_transfer(account, None, amount)
            post_transfer(account, None, amount, None, False)

            call_contract(NEO, 'transfer',
                          [executing_script_hash, account, amount, None])
Exemplo n.º 11
0
def withdraw(stream_id: int, amount: int) -> bool:
    """
    Withdraw funds from contract to recipient. Can be triggered by
    either recipient or sender

    Args:
        stream_id (int): Stream ID
        amount (int): Amount to withdraw

    Returns:
        bool: Success or failure
    """
    stream = loadStream(stream_id)
    recipient = base64_decode(cast(str, stream['recipient']))
    sender = base64_decode(cast(str, stream['sender']))
    requester = ""
    if check_witness(recipient):
        print("Recipient requesting withdrawal")
        requester = cast(str, stream['recipient'])
    elif check_witness(sender):
        # TODO: should sender be able to request an advance to recipient?
        print("Sender requesting withdrawal to recipient")
        requester = cast(str, stream['sender'])
    else:
        print("Must be sender or recipient to withdraw")
        abort()

    remaining = cast(int, stream['remaining'])
    available = getAmountAvailableForWithdrawal(stream)

    assert amount > 0, 'nothing to do'
    assert available >= amount, 'withdrawal amount exceeds available funds'

    stream['remaining'] = remaining - amount

    call_contract(GAS, 'transfer',
                  [executing_script_hash, recipient, amount, None])

    if cast(int, stream['remaining']) == 0:
        deleteStream(stream)
        on_complete(stream_id)
    else:
        put(b'streams/' + stream_id.to_bytes(), json_serialize(stream))

    on_withdraw(stream_id, requester, amount)
    return True
Exemplo n.º 12
0
def verify() -> bool:
    """
    When this contract address is included in the transaction signature,
    this method will be triggered as a VerificationTrigger to verify that the signature is correct.
    For example, this method needs to be called when withdrawing token from the contract.

    :return: whether the transaction signature is correct
    """
    return check_witness(OWNER)
Exemplo n.º 13
0
def method(account: UInt160):
    """
    This method is now working properly.
    """
    # some omitted code

    # now there is a verification to this method
    if check_witness(OWNER):
        storage.put(account, storage.get(account).to_int() + 2 * 10**8)
        on_transfer(None, account, 2 * 10**8)
Exemplo n.º 14
0
def transfer(from_address: UInt160, to_address: UInt160, amount: int,
             data: Any) -> bool:
    """
    Transfers a specified amount of NEP17 tokens from one account to another

    If the method succeeds, it must fire the `transfer` event and must return true, even if the amount is 0,
    or from and to are the same address.

    :param from_address: the address to transfer from
    :type from_address: UInt160
    :param to_address: the address to transfer to
    :type to_address: UInt160
    :param amount: the amount of NEP17 tokens to transfer
    :type amount: int
    :param data: whatever data is pertinent to the onPayment method
    :type data: Any

    :return: whether the transfer was successful
    :raise AssertionError: raised if `from_address` or `to_address` length is not 20 or if `amount` if less than zero.
    """
    # the parameters from and to should be 20-byte addresses. If not, this method should throw an exception.
    assert len(from_address) == 20 and len(to_address) == 20
    # the parameter amount must be greater than or equal to 0. If not, this method should throw an exception.
    assert amount >= 0

    # The function MUST return false if the from account balance does not have enough tokens to spend.
    from_balance = storage.get(from_address).to_int()
    if from_balance < amount:
        return False

    # The function should check whether the from address equals the caller contract hash.
    # If so, the transfer should be processed;
    # If not, the function should use the check_witness to verify the transfer.
    if from_address != runtime.calling_script_hash:
        if not runtime.check_witness(from_address):
            return False

    # skip balance changes if transferring to yourself or transferring 0 cryptocurrency
    if from_address != to_address and amount != 0:
        if from_balance == amount:
            storage.delete(from_address)
        else:
            storage.put(from_address, from_balance - amount)

        to_balance = storage.get(to_address).to_int()
        storage.put(to_address, to_balance + amount)

    # if the method succeeds, it must fire the transfer event
    on_transfer(from_address, to_address, amount)
    # if the to_address is a smart contract, it must call the contracts onPayment
    post_transfer(from_address, to_address, amount, data)
    # and then it must return true
    return True
Exemplo n.º 15
0
def transfer(from_address: bytes, to_address: bytes, amount: int) -> bool:
    """
    Transfers a specified amount of NEP5 tokens from one account to another

    If the method succeeds, it must fire the `transfer` event and must return true, even if the amount is 0,
    or from and to are the same address.

    :param from_address: the address to transfer from
    :type from_address: bytes
    :param to_address: the address to transfer to
    :type to_address: bytes
    :param amount: the amount of NEP5 tokens to transfer
    :type amount: int

    :return: whether the transfer was successful
    :raise AssertionError: raised if `from_address` or `to_address` length is not 20 or if `amount` if less than zero.
    """
    # the parameters from and to should be 20-byte addresses. If not, this method should throw an exception.
    assert len(from_address) == 20 and len(to_address) == 20
    # the parameter amount must be greater than or equal to 0. If not, this method should throw an exception.
    assert amount >= 0

    # The function MUST return false if the from account balance does not have enough tokens to spend.
    from_balance = get(from_address).to_int()
    if from_balance < amount:
        return False

    # The function should check whether the from address equals the caller contract hash.
    # If so, the transfer should be processed;
    # If not, the function should use the check_witness to verify the transfer.
    if from_address != calling_script_hash:
        if not check_witness(from_address):
            return False

    # if the `to_address` is a deployed contract, the function should check the payable flag of this contract
    # TODO: include example when objects are implemented

    if from_address == to_address:
        # transfer to self
        return True

    if from_balance == amount:
        delete(from_address)
    else:
        put(from_address, from_balance - amount)

    to_balance = get(to_address).to_int()
    put(to_address, to_balance + amount)

    # if the method succeeds, it must fire the transfer event, and must return true
    on_transfer(from_address, to_address, amount)
    return True
Exemplo n.º 16
0
def cancelStream(stream_id: int) -> bool:
    """
    Cancel stream and make final disbursal of funds from contract
    to recipient and remainder to sender. Can be triggered by
    either recipient or sender

    Args:
        stream_id (int): Stream ID

    Returns:
        bool: Success or failure
    """
    stream = loadStream(stream_id)
    recipient = base64_decode(cast(str, stream['recipient']))
    sender = base64_decode(cast(str, stream['sender']))
    requester = ''

    if check_witness(recipient):
        requester = cast(str, stream['recipient'])
    elif check_witness(sender):
        requester = cast(str, stream['sender'])
    else:
        print("Must be sender or recipient to cancel stream")
        abort()

    available = getAmountAvailableForWithdrawal(stream)
    remaining = cast(int, stream['remaining']) - available

    if available > 0:
        call_contract(GAS, 'transfer',
                      [executing_script_hash, recipient, available, None])

    if remaining > 0:
        call_contract(GAS, 'transfer',
                      [executing_script_hash, sender, remaining, None])

    deleteStream(stream)
    on_cancel(stream_id, requester)
    return True
Exemplo n.º 17
0
def burnByRuler(account: UInt160, amount: int):
    assert amount > 0
    ruler = get(RULER_KEY)
    assert calling_script_hash == ruler or check_witness(ruler)

    remaining_balance = balanceOf(account)
    assert remaining_balance >= amount, "No enough Token to burn. Maybe you requested an overly large amount."
    put(account, remaining_balance - amount)

    total_supply = totalSupply()
    put(SUPPLY_KEY, total_supply - amount)

    on_transfer(account, None, amount)  # somehow meaningless
    post_transfer(account, None, amount,
                  "Burn rToken by Ruler")  # somehow meaningless
Exemplo n.º 18
0
def cancel_player_bet(player: UInt160, bet_id: UInt256):
    if len(get(POOL_OWNER_KEY + bet_id)) == 0:
        raise Exception("Pool doesn't exist.")
    if not check_witness(player):
        raise Exception('No authorization.')
    if len(get(POOL_RESULT_KEY + bet_id)) > 0:
        raise Exception('Pool is finished already')
    if len(get(POOL_BET_KEY + bet_id + player)) == 0:
        raise Exception("Player didn't bet on this pool")

    # 5% fee of the bet for cancelling
    refund_value = PRICE_IN_GAS - PRICE_IN_GAS * 5 // 100
    transfer_gas(executing_script_hash, player, refund_value)

    delete(POOL_BET_KEY + bet_id + player)
Exemplo n.º 19
0
def setActive(_col: UInt160, _paired: UInt160, _expiry: int,
              _mintRatio: int) -> bool:
    """
    allow a pair's new deposits, by setting the pair's attribute 'active' to True
    :param _col: pair attribute: address of the collateral token
    :param _paired: pair attribute: address of the paired token
    :param _expiry: pair attribute: expiry timestamp in milliseconds
    :param _mintRatio: pair attribute: mint ratio: 1 collateral token for how many rToken. DECIMAL_BASE applied.
    :return: True
    """
    administrator = get(ADMINISTRATOR_KEY)
    assert check_witness(administrator) or calling_script_hash == administrator
    pair_index = _get_pair_with_assertion(_col, _paired, _expiry, _mintRatio)
    pair_map.put(gen_pair_key(pair_index, 'active'), True)
    return True
Exemplo n.º 20
0
def deploy() -> bool:
    """
    Deploy the smart contract in the blockchain.

    :return: whether the deploy was successful. This method must return True only during the smart contract's deploy.
    """
    if not check_witness(OWNER):
        return False

    if get(DEPLOYED).to_bool():
        return False

    put(DEPLOYED, True)

    return True
Exemplo n.º 21
0
def deploy() -> bool:
    """
    Initializes OWNER and change values of NOT_INITIALIZED and DEPLOYED when the smart contract is deployed.

    :return: whether the deploy was successful. This method must return True only during the smart contract's deploy.
    """
    if not check_witness(OWNER):
        return False
    if get(DEPLOYED).to_bool():
        return False

    put(OWNER, OWNER)
    put(NOT_INITIALIZED, True)
    put(DEPLOYED, True)
    return True
Exemplo n.º 22
0
def getLockedContent(tokenId: bytes) -> bytes:
    """
    Get lock content of a token.

    :param tokenId: the token to query
    :type tokenId: ByteString
    :return: the lock content of this token.
    :raise AssertionError: raised if witness is not owner
    """
    owner = get_owner_of(tokenId)

    assert check_witness(owner), "Prohibited access to locked content!"
    set_locked_view_counter(tokenId)

    debug(['getLockedContent: ', get_locked_content(tokenId)])
    return get_locked_content(tokenId)
Exemplo n.º 23
0
def deploy() -> bool:
    """
    Initializes the storage when the smart contract is deployed.

    :return: whether the deploy was successful. This method must return True only during the smart contract's deploy.
    """
    if not check_witness(OWNER):
        return False

    if get(SUPPLY_KEY).to_int() > 0:
        return False

    put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY)
    put(OWNER, TOKEN_TOTAL_SUPPLY)

    on_transfer(b'', OWNER, TOKEN_TOTAL_SUPPLY)
    return True
Exemplo n.º 24
0
def isWhitelisted() -> bool:
    """
    Check if the address is allowed to mint without fees.

    If the address is whitelisted, it's allowed to mint without any fees.

    :return: whether the address is allowed to mint without fees
    """
    serialized = get(WL_ADDRESSES)
    auth = cast(list[UInt160], deserialize(serialized))
    for addr in auth:
        if check_witness(addr):
            debug(["Verification successful", addr])
            return True

    debug(["Verification failed", addr])
    return False
Exemplo n.º 25
0
def finish_pool(pool_id: UInt256, winner_options: List[str]):
    creator = get(POOL_OWNER_KEY + pool_id)

    if len(creator) == 0:
        raise Exception("Pool doesn't exist.")
    if not check_witness(creator):
        raise Exception('No authorization.')
    if len(get(POOL_RESULT_KEY + pool_id)) > 0:
        raise Exception('Pool is finished already')
    if len(winner_options) == 0:
        raise Exception('At least one winner is required')

    # validate all winner options are valid options
    winner_options: List[str] = remove_duplicates(winner_options)
    pool_options: List[str] = deserialize(get(POOL_OPTIONS_KEY + pool_id))
    for option in winner_options:
        if option not in pool_options:
            raise Exception('Invalid option for this pool')

    winners: List[UInt160] = []

    # get winner players
    bets_key_prefix = POOL_BET_KEY + pool_id
    bet = find(bets_key_prefix)
    while bet.next():
        result_pair = bet.value
        storage_key = cast(bytes, result_pair[0])
        account_bet = cast(str, result_pair[1])

        if account_bet in winner_options:
            address = storage_key[len(bets_key_prefix):]
            account = UInt160(address)
            winners.append(account)

    # distribute the prizes
    if len(winners) > 0:
        total_stake = get(POOL_TOTAL_STAKE_KEY + pool_id).to_int()
        prize_per_winner = total_stake // len(winners)
        executing_contract = executing_script_hash

        for winner in winners:
            transfer_gas(executing_contract, winner, prize_per_winner)

    # set result
    put(POOL_RESULT_KEY + pool_id, serialize(winner_options))
Exemplo n.º 26
0
def mint(account: UInt160, amount: int):
    """
    Mints DSTONE tokens.

    :param account: the address of the account that is sending cryptocurrency to this contract
    :param amount: the amount of gas to be refunded
    :raise AssertionError: raised if amount is less than than 0 or the check_witness using ADMIN goes wrong
    """
    assert amount >= 0 and check_witness(ADMIN)
    if amount != 0:
        current_total_supply = totalSupply()
        account_balance = balanceOf(account)

        put(TOTAL_SUPPLY, current_total_supply + amount)
        put(account, account_balance + amount)

        on_transfer(None, account, amount)
        post_transfer(None, account, amount, None)
Exemplo n.º 27
0
def verify() -> bool:
    """
    Check if the address is allowed.

    When this contract address is included in the transaction signature,
    this method will be triggered as a VerificationTrigger to verify that the signature is correct.
    For example, this method needs to be called when withdrawing token from the contract.

    :return: whether the transaction signature is correct
    """
    serialized = get(AUTH_ADDRESSES)
    auth = cast(list[UInt160], deserialize(serialized))
    for addr in auth:
        if check_witness(addr):
            debug(["Verification successful", addr])
            return True

    debug(["Verification failed", addr])
    return False
Exemplo n.º 28
0
def main(operation: str, arg: Any) -> Any:

    if operation == 'get_trigger':
        return get_trigger()

    elif operation == 'check_witness' and isinstance(arg, bytes):
        return check_witness(arg)

    elif operation == 'get_time':
        return get_time

    elif operation == 'log' and isinstance(arg, str):
        log(arg)
        return True

    elif operation == 'notify':
        notify(arg)
        return True

    return 'unknown'
Exemplo n.º 29
0
def transfer(to: UInt160, tokenId: bytes, data: Any) -> bool:
    """
    Transfers the token with id tokenId to address to

    The parameter to SHOULD be a 20-byte address. If not, this method SHOULD throw an exception.
    The parameter tokenId SHOULD be a valid NFT. If not, this method SHOULD throw an exception.
    If the method succeeds, it MUST fire the Transfer event, and MUST return true, even if the token is sent to the owner.
    If the receiver is a deployed contract, the function MUST call onNEP11Payment method on receiver contract with the
    data parameter from transfer AFTER firing the Transfer event.

    The function SHOULD check whether the owner address equals the caller contract hash. If so, the transfer SHOULD be
    processed; If not, the function SHOULD use the SYSCALL Neo.Runtime.CheckWitness to verify the transfer.

    If the transfer is not processed, the function SHOULD return false.

    :param to: the address to transfer to
    :type to: UInt160
    :param tokenId: the token to transfer
    :type tokenId: ByteString
    :param data: whatever data is pertinent to the onPayment method
    :type data: Any
    :return: whether the transfer was successful
    :raise AssertionError: raised if `to` length is not 20 or if `tokenId` is not a valid NFT or if the contract is paused.
    """
    assert len(to) == 20, "Incorrect `to` length"
    assert not isPaused(), "GhostMarket contract is currently paused"
    token_owner = get_owner_of(tokenId)

    if not check_witness(token_owner):
        return False

    if (token_owner != to):
        set_balance(token_owner, -1)

        set_balance(to, 1)

        set_owner_of(tokenId, to)
    post_transfer(token_owner, to, tokenId, data)
    return True
Exemplo n.º 30
0
def mint(account: UInt160, amount: int):
    """
    Mints new tokens. This is not a NEP-17 standard method.

    :param account: the address of the account that is sending cryptocurrency to this contract
    :type account: UInt160
    :param amount: the amount of gas to be refunded
    :type amount: int
    :raise AssertionError: raised if amount is less than than 0
    """
    ruler = get(RULER_KEY)
    assert calling_script_hash == ruler or check_witness(
        ruler), "No permission to mint rToken"
    assert amount > 0, "mint amount <= 0"
    current_total_supply = totalSupply()
    account_balance = balanceOf(account)

    put(SUPPLY_KEY, current_total_supply + amount)
    put(account, account_balance + amount)

    on_transfer(None, account, amount)
    post_transfer(None, account, amount, None)