示例#1
0
文件: test_cli.py 项目: uivlis/sto
def test_payout_deploy(
        private_key_hex,
        db_path,
        monkeypatch_create_web3,
        monkeypatch_get_contract_deployed_tx,
        get_contract_deployed_tx,
        click_runner,
        dbsession,
        web3,
        security_token,
        kyc_contract,
        test_token,
        test_token_name
):
    result = click_runner.invoke(
        cli,
        [
            '--database-file', db_path,
            '--ethereum-private-key', private_key_hex,
            '--ethereum-gas-price', 20,
            'payout-deploy',
            '--token-address', security_token,
            '--payout-token-address', test_token,
            '--payout-token-name', test_token_name,
            '--kyc-address', kyc_contract,
            '--payout-name', 'Pay X',
            '--uri', 'http://tokenmarket.net',
            '--type', 0
        ]
    )
    assert result.exit_code == 0
    abi = get_abi(None)['PayoutContract']
    tx = get_contract_deployed_tx(dbsession, 'PayoutContract')
    contract = web3.eth.contract(address=tx.contract_address, abi=abi['abi'], bytecode=abi['bytecode'])
    assert contract.functions.blockNumber().call() == web3.eth.blockNumber
示例#2
0
文件: main.py 项目: uivlis/sto
def payout_deposit(config: BoardCommmadConfiguration):
    """
    the private key here needs to belong to the customer who wants to fetch tokens
    """
    from sto.ethereum.utils import (get_contract_deployed_tx, create_web3,
                                    get_abi, broadcast as _broadcast)
    from sto.ethereum.txservice import EthereumStoredTXService
    from sto.models.implementation import BroadcastAccount, PreparedTransaction

    tx = get_contract_deployed_tx(config.dbsession, 'PayoutContract')
    if not tx:
        raise Exception(
            'PayoutContract not found. Call payout-deploy to deploy PayoutContract'
        )
    web3 = create_web3(config.ethereum_node_url)
    service = EthereumStoredTXService(config.network, config.dbsession, web3,
                                      config.ethereum_private_key,
                                      config.ethereum_gas_price,
                                      config.ethereum_gas_limit,
                                      BroadcastAccount, PreparedTransaction)

    abi = get_abi(config.ethereum_abi_file)
    service.interact_with_contract(contract_name='PayoutContract',
                                   abi=abi,
                                   address=tx.contract_address,
                                   note='calling fetchTokens',
                                   func_name='fetchTokens',
                                   args={})
    _broadcast(config)
示例#3
0
文件: main.py 项目: uivlis/sto
def payout_dividends(config: BoardCommmadConfiguration, transfer_amount):
    from sto.ethereum.utils import (get_contract_deployed_tx, create_web3,
                                    get_abi, broadcast as _broadcast)
    from sto.ethereum.txservice import EthereumStoredTXService
    from sto.models.implementation import BroadcastAccount, PreparedTransaction

    tx = get_contract_deployed_tx(config.dbsession, 'PayoutContract')
    if not tx:
        raise Exception(
            'PayoutContract not found. Call payout-deploy to deploy PayoutContract'
        )
    web3 = create_web3(config.ethereum_node_url)
    service = EthereumStoredTXService(config.network, config.dbsession, web3,
                                      config.ethereum_private_key,
                                      config.ethereum_gas_price,
                                      config.ethereum_gas_limit,
                                      BroadcastAccount, PreparedTransaction)
    abi = get_abi(config.ethereum_abi_file)
    service.interact_with_contract(
        contract_name='PayoutContract',
        abi=abi,
        address=tx.contract_address,
        note='transferring amount: {0}'.format(transfer_amount),
        func_name='act',
        args={'amount': transfer_amount})
    _broadcast(config)
示例#4
0
文件: main.py 项目: uivlis/sto
def payout_approve(
    config: BoardCommmadConfiguration,
    payout_token_address: str,
    payout_token_name: str,
):
    """
    approve tokens to the payout contract
    """
    from sto.ethereum.utils import (get_contract_deployed_tx, create_web3,
                                    get_abi, broadcast as _broadcast,
                                    priv_key_to_address)
    from sto.ethereum.txservice import EthereumStoredTXService
    from sto.models.implementation import BroadcastAccount, PreparedTransaction

    tx = get_contract_deployed_tx(config.dbsession, 'PayoutContract')
    if not tx:
        raise Exception(
            'PayoutContract not found. Call payout-deploy to deploy PayoutContract'
        )
    if payout_token_name:
        tx = get_contract_deployed_tx(config.dbsession, payout_token_name)
        payout_token_address = tx.contract_address
    if payout_token_address is None:
        raise Exception('''
            Either payout token is not deployed or --payout-token-address not provided
            ''')
    tx = get_contract_deployed_tx(config.dbsession, 'PayoutContract')
    if not tx:
        raise Exception(
            'PayoutContract not found. Call payout-deploy to deploy PayoutContract'
        )
    payout_contract_address = tx.contract_address

    web3 = create_web3(config.ethereum_node_url)
    service = EthereumStoredTXService(config.network, config.dbsession, web3,
                                      config.ethereum_private_key,
                                      config.ethereum_gas_price,
                                      config.ethereum_gas_limit,
                                      BroadcastAccount, PreparedTransaction)
    abi = get_abi(config.ethereum_abi_file)
    payout_token_contract = web3.eth.contract(
        address=payout_token_address, abi=abi[payout_token_name]['abi'])
    service.interact_with_contract(
        payout_token_name,
        abi,
        payout_token_address,
        'approving tokens',
        'approve',
        args={
            '_spender':
            payout_contract_address,
            '_value':
            payout_token_contract.functions.balanceOf(
                priv_key_to_address(config.ethereum_private_key)).call()
        },
        use_bytecode=False)
    _broadcast(config)
示例#5
0
文件: test_cli.py 项目: selendra/sto
def test_payout_deposit(private_key_hex, db_path, monkeypatch_create_web3,
                        monkeypatch_get_contract_deployed_tx,
                        get_contract_deployed_tx, click_runner, dbsession,
                        web3, security_token, kyc_contract, test_token,
                        test_token_name):
    abi = get_abi(None)

    # deploy contract
    result = click_runner.invoke(cli, [
        '--database-file', db_path, '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-price', 9999999, 'payout-deploy', '--token-address',
        security_token, '--payout-token-address', test_token,
        '--payout-token-name', test_token_name, '--kyc-address', kyc_contract,
        '--payout-name', 'Pay X', '--uri', 'http://tokenmarket.net', '--type',
        0, '--options', [
            "Vested for dividend",
        ]
    ])
    assert result.exit_code == 0

    test_token_contract = web3.eth.contract(address=test_token,
                                            abi=abi[test_token_name]['abi'])

    result = click_runner.invoke(cli, [
        '--database-file', db_path, '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-price', 9999999, 'payout-approve',
        '--payout-token-name', test_token_name
    ])
    assert result.exit_code == 0
    payout_contract_address = get_contract_deployed_tx(
        dbsession, 'PayoutContract').contract_address
    payout_contract = web3.eth.contract(address=payout_contract_address,
                                        abi=abi['PayoutContract']['abi'])
    initial_balance = test_token_contract.call().balanceOf(
        payout_contract_address)
    result = click_runner.invoke(cli, [
        '--database-file', db_path, '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-price', 9999999, 'payout-deposit'
    ])
    assert result.exit_code == 0
    assert test_token_contract.functions.balanceOf(
        payout_contract.address).call() > initial_balance
    # check if payouts happen
    initial_balance = test_token_contract.call().balanceOf(
        priv_key_to_address(private_key_hex))
    payout_contract.functions.act(123).transact(
        {"from": priv_key_to_address(private_key_hex)})
    # 0x0000000000000000000000000000000000000064 is the default address 100
    assert payout_contract.functions.balanceOf(
        '0x0000000000000000000000000000000000000064').call() == 123
    assert test_token_contract.call().balanceOf(
        priv_key_to_address(private_key_hex)) > initial_balance
示例#6
0
def distribute_single(logger: Logger, dbsession: Session, network: str,
                      ethereum_node_url: Union[str, Web3],
                      ethereum_abi_file: Optional[str],
                      ethereum_private_key: Optional[str],
                      ethereum_gas_limit: Optional[int],
                      ethereum_gas_price: Optional[int], token_address: str,
                      ext_id: str, email: str, name: str, to_address: str,
                      amount: Decimal) -> bool:
    """Send out a single transfer.

    :return: True if a new tx for broadcasting was created
    """

    d = DistributionEntry(ext_id, email, name, to_address, amount)

    check_good_private_key(ethereum_private_key)

    abi = get_abi(ethereum_abi_file)

    web3 = create_web3(ethereum_node_url)

    service = EthereumStoredTXService(network, dbsession, web3,
                                      ethereum_private_key, ethereum_gas_price,
                                      ethereum_gas_limit, BroadcastAccount,
                                      PreparedTransaction)

    logger.info(
        "Starting creating distribution transactions for %s token from nonce %s",
        token_address, service.get_next_nonce())

    total = d.amount * 10**18

    available = service.get_raw_token_balance(token_address, abi)
    if total > available:
        raise NotEnoughTokens(
            "Not enough tokens for distribution. Account {} has {} raw token balance, needed {}"
            .format(service.get_or_create_broadcast_account().address,
                    available, total))

    if not service.is_distributed(d.external_id, token_address):
        # Going to tx queue
        raw_amount = int(d.amount * 10**18)
        note = "Distributing tokens, raw amount: {}".format(raw_amount)
        service.distribute_tokens(d.external_id, d.address, raw_amount,
                                  token_address, abi, note)
        logger.info("New broadcast has been created")
        return True
    else:
        logger.error("Already distributed")
        return False
示例#7
0
def distribute_tokens(logger: Logger, dbsession: Session, network: str,
                      ethereum_node_url: Union[str, Web3],
                      ethereum_abi_file: Optional[str],
                      ethereum_private_key: Optional[str],
                      ethereum_gas_limit: Optional[int],
                      ethereum_gas_price: Optional[int], token_address: str,
                      dists: List[DistributionEntry]) -> Tuple[int, int]:
    """Sends tokens to their first owners in primary markets."""

    check_good_private_key(ethereum_private_key)

    abi = get_abi(ethereum_abi_file)

    web3 = create_web3(ethereum_node_url)

    service = EthereumStoredTXService(network, dbsession, web3,
                                      ethereum_private_key, ethereum_gas_price,
                                      ethereum_gas_limit, BroadcastAccount,
                                      PreparedTransaction)

    logger.info(
        "Starting creating distribution transactions for %s token from nonce %s",
        token_address, service.get_next_nonce())

    total = sum([dist.amount * 10**18 for dist in dists])

    available = service.get_raw_token_balance(token_address, abi)
    if total > available:
        raise NotEnoughTokens(
            "Not enough tokens for distribution. Account {} has {} raw token balance, needed {}"
            .format(service.get_or_create_broadcast_account().address,
                    available, total))

    new_distributes = old_distributes = 0

    for d in tqdm(dists):
        if not service.is_distributed(d.external_id, token_address):
            # Going to tx queue
            raw_amount = int(d.amount * 10**18)
            note = "Distributing tokens, raw amount: {}".format(raw_amount)
            service.distribute_tokens(d.external_id, d.address, raw_amount,
                                      token_address, abi, note)
            new_distributes += 1
        else:
            # CSV reimports
            old_distributes += 1

    logger.info("Prepared transactions for broadcasting for network %s",
                network)
    return new_distributes, old_distributes
示例#8
0
文件: test_cli.py 项目: selendra/sto
        def _execute(config, contract_name, contract_function_name, args):
            from sto.ethereum.txservice import EthereumStoredTXService
            from sto.models.implementation import BroadcastAccount, PreparedTransaction
            from sto.ethereum.utils import broadcast

            service = EthereumStoredTXService(
                config.network, config.dbsession, web3,
                config.ethereum_private_key, config.ethereum_gas_price,
                config.ethereum_gas_limit, BroadcastAccount,
                PreparedTransaction)
            abi = get_abi(None)
            tx = get_contract_deployed_tx(dbsession, contract_name)
            service.interact_with_contract(contract_name, abi,
                                           tx.contract_address, '',
                                           contract_function_name, args)
            broadcast(config)
示例#9
0
def token_contract(sample_token, web3) -> Contract:
    """Proxied ABI to the deployed SecurityToken token contract."""

    contract_name = "SecurityToken"

    abi = get_abi(None)

    abi_data = abi[contract_name]

    contract_class = Contract.factory(
        web3=web3,
        abi=abi_data["abi"],
        bytecode=abi_data["bytecode"],
        bytecode_runtime=abi_data["bytecode_runtime"],
    )

    return contract_class(address=sample_token)
示例#10
0
文件: issuance.py 项目: mandlamag/sto
def contract_status(logger: Logger, dbsession: Session, network: str,
                    ethereum_node_url: str, ethereum_abi_file: str,
                    ethereum_private_key: str, ethereum_gas_limit: str,
                    ethereum_gas_price: str, token_contract: str):
    """Poll STO contract status."""

    abi = get_abi(ethereum_abi_file)

    web3 = create_web3(ethereum_node_url)

    service = EthereumStoredTXService(network, dbsession, web3,
                                      ethereum_private_key, ethereum_gas_price,
                                      ethereum_gas_limit, BroadcastAccount,
                                      PreparedTransaction)
    contract = service.get_contract_proxy("SecurityToken", abi, token_contract)

    try:
        logger.info("Name: %s", contract.functions.name().call())
        logger.info("Symbol: %s", contract.functions.symbol().call())
        supply = contract.functions.totalSupply().call()
        human_supply = Decimal(supply) / Decimal(
            10**contract.functions.decimals().call())
        raw_balance = contract.functions.balanceOf(
            service.get_or_create_broadcast_account().address).call()
        normal_balance = Decimal(raw_balance) / Decimal(
            10**contract.functions.decimals().call())
        logger.info("Total supply: %s", human_supply)
        logger.info("Decimals: %d", contract.functions.decimals().call())
        logger.info("Owner: %s", contract.functions.owner().call())
        logger.info("Broadcast account token balance: %f", normal_balance)
        logger.info("Transfer verified: %s",
                    contract.functions.transferVerifier().call())
    except BadFunctionCallOutput as e:
        raise BadContractException(
            "Looks like this is not a token contract address. Please check on EtherScan that the address presents the token contract"
        )

    return {
        "name": contract.functions.name().call(),
        "symbol": contract.functions.symbol().call(),
        "totalSupply": contract.functions.totalSupply().call(),
        "broadcastBalance": raw_balance,
    }
示例#11
0
文件: test_cli.py 项目: selendra/sto
def test_kyc_manage(dbsession, private_key_hex, web3, db_path,
                    monkeypatch_create_web3,
                    monkeypatch_get_contract_deployed_tx,
                    get_contract_deployed_tx, click_runner):
    result = click_runner.invoke(cli, [
        '--database-file', db_path, '--ethereum-private-key', private_key_hex,
        'kyc-deploy'
    ])
    assert result.exit_code == 0
    tx = get_contract_deployed_tx(dbsession, 'BasicKYC')
    abi = get_abi(None)
    kyc_contract = web3.eth.contract(address=tx.contract_address,
                                     abi=abi['BasicKYC']['abi'])

    eth_address = web3.eth.account.create().address

    result = click_runner.invoke(cli, [
        '--database-file', db_path, '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 80000, 'kyc-manage', '--whitelist-address',
        eth_address
    ])
    assert result.exit_code == 0
    assert kyc_contract.functions.isWhitelisted(eth_address).call() == True
示例#12
0
文件: issuance.py 项目: mandlamag/sto
def deploy_token_contracts(
        logger: Logger, dbsession: Session, network: str,
        ethereum_node_url: Union[str, Web3], ethereum_abi_file: Optional[str],
        ethereum_private_key: Optional[str], ethereum_gas_limit: Optional[int],
        ethereum_gas_price: Optional[int], name: str, symbol: str, url: str,
        amount: int, transfer_restriction: str):
    """Issue out a new Ethereum token."""

    assert type(amount) == int
    decimals = 18  # Everything else is bad idea

    check_good_private_key(ethereum_private_key)

    abi = get_abi(ethereum_abi_file)

    web3 = create_web3(ethereum_node_url)

    # We do not have anything else implemented yet
    assert transfer_restriction == "unrestricted"

    service = EthereumStoredTXService(network, dbsession, web3,
                                      ethereum_private_key, ethereum_gas_price,
                                      ethereum_gas_limit, BroadcastAccount,
                                      PreparedTransaction)

    # Deploy security token
    note = "Deploying token contract for {}".format(name)
    deploy_tx1 = service.deploy_contract("SecurityToken",
                                         abi,
                                         note,
                                         constructor_args={
                                             "_name": name,
                                             "_symbol": symbol,
                                             "_url": url
                                         })  # See SecurityToken.sol

    # Deploy transfer agent
    note = "Deploying unrestricted transfer policy for {}".format(name)
    deploy_tx2 = service.deploy_contract("UnrestrictedTransferAgent", abi,
                                         note)

    # Set transfer agent
    note = "Making transfer restriction policy for {} effective".format(name)
    contract_address = deploy_tx1.contract_address
    update_tx1 = service.interact_with_contract(
        "SecurityToken", abi, contract_address, note, "setTransactionVerifier",
        {"newVerifier": deploy_tx2.contract_address})

    # Issue out initial shares
    note = "Creating {} initial shares for {}".format(amount, name)
    contract_address = deploy_tx1.contract_address
    amount_18 = int(amount * 10**decimals)
    update_tx2 = service.interact_with_contract("SecurityToken", abi,
                                                contract_address, note,
                                                "issueTokens",
                                                {"value": amount_18})

    logger.info("Prepared transactions for broadcasting for network %s",
                network)
    logger.info("STO token contract address will be %s%s%s",
                colorama.Fore.LIGHTGREEN_EX, deploy_tx1.contract_address,
                colorama.Fore.RESET)
    return [deploy_tx1, deploy_tx2, update_tx1, update_tx2]