Example #1
0
def _get_contract(address, filename, contract_name):
    compiler = ContractCompiler()
    w3 = get_w3()

    interface = compiler.get_contract_interface(filename, contract_name)
    contract = w3.eth.contract(abi=interface['abi'], address=address)

    return contract
Example #2
0
    def resolve_get_merge_asc_abi(self, info):
        contract_compiler = ContractCompiler()

        merge_asc_interface = contract_compiler.get_contract_interface(
            "merge_asc.sol", "MergeASC")
        return {
            'abi': merge_asc_interface['abi'],
            'unlinked_binary': merge_asc_interface['bin']
        }
Example #3
0
def get_merge_module_instance(project: Project, compiler: ContractCompiler, w3: Web3):
    base_dao_interface = compiler.get_contract_interface('base_dao.sol', 'BaseDao')
    base_dao_contract = w3.eth.contract(abi=base_dao_interface['abi'], address=project.dao_address)

    merge_address = base_dao_contract.functions.getModuleByCode(1).call()

    merge_module_interface = compiler.get_contract_interface('merge_module.sol', 'MergeModule')
    merge_module_contract = w3.eth.contract(abi=merge_module_interface['abi'], address=merge_address)

    return merge_module_contract
Example #4
0
def process_merges():
    projects = Project.objects.filter()
    compiler = ContractCompiler()
    w3 = deploy.get_w3()

    for project in projects:
        if project.is_mycro_dao:
            continue
        if project.blockchain_state != BlockchainState.COMPLETED:
            continue
        logger.info(f"Looking for PRs for project {project.dao_address}")

        merge_contract = get_merge_module_instance(project, compiler, w3)

        logger.info(f"Found PRs: {merge_contract.functions.pullRequestsToMerge().call()}")
        for pr_id in merge_contract.functions.pullRequestsToMerge().call():
            logger.info(f"DAO {project.dao_address} with name {project.repo_name} wants to merge {pr_id}")

            # TODO get rid of this try catch
            # We can do this when we use get_new_entries but need this for now because we reattempt to merge PRs even
            # after they've been merged which results in an exception
            try:
                github.merge_pr(project.repo_name, pr_id, organization=settings.github_organization())
            except Exception as e:
                logger.warning(
                    f'PR {pr_id} for project {project.repo_name} could not be merged, probably because it already has been')
                logger.warning(e)
Example #5
0
    def mutate(self, info, dao_address: str, rewardee: str, reward: int,
               pr_id: int):
        # validate that we have a DAO with the given address in our DB
        # this may be unnecessary
        project = Project.objects.get(dao_address=dao_address)

        # TODO check that a PR with the given ID exists before executing the rest of this function
        CreateMergeASC._validate_asc_creation(project, pr_id)

        compiler = ContractCompiler()

        w3 = deploy.get_w3()
        base_dao_interface = compiler.get_contract_interface(
            'base_dao.sol', 'BaseDao')
        dao_contract = w3.eth.contract(abi=base_dao_interface['abi'],
                                       address=dao_address)

        asc_interface = compiler.get_contract_interface(
            'merge_asc.sol', 'MergeASC')

        # we don't use the async method here because we can't parallelize
        # first the asc has to be deployed to get it's address then the address has to be registered
        # with the base dao
        _, _, asc_address, _ = deploy.deploy(
            asc_interface,
            rewardee,
            reward,
            pr_id,
            private_key=Wallet.objects.first().private_key)

        deploy.call_contract_function(
            dao_contract.functions.propose,
            asc_address,
            private_key=Wallet.objects.first().private_key)

        asc = project.asc_set.create(
            address=asc_address,
            project=project,
            rewardee=rewardee,
            reward=reward,
            pr_id=pr_id,
            blockchain_state=BlockchainState.COMPLETED.value)

        return CreateMergeASC(asc=asc)
Example #6
0
def create_asc(self, asc_id):

    logger.info(f'Attempting to get lock to create asc {asc_id}')

    with REDIS_CLIENT.lock(REDIS_CREATE_CONTRACT_LOCK):
        logger.info(f'Acquired lock to create asc {asc_id}')

        asc = ASC.objects.get(id=asc_id)

        assert asc.blockchain_state == BlockchainState.PENDING, "Blockchain state must be pending"
        assert not asc.address, "ASC must not already have an address"

        compiler = ContractCompiler()

        w3 = deploy.get_w3()
        base_dao_interface = compiler.get_contract_interface('base_dao.sol',
                                                             'BaseDao')
        dao_contract = w3.eth.contract(abi=base_dao_interface['abi'],
                                       address=asc.project.dao_address)

        asc_interface = compiler.get_contract_interface('merge_asc.sol',
                                                        'MergeASC')

        # we don't use the async method here because we can't parallelize
        # first the asc has to be deployed to get it's address then the address has to be registered
        # with the base dao
        _, _, asc_address, _ = deploy.deploy(asc_interface, asc.rewardee, asc.reward,
                                             asc.pr_id,
                                             private_key=Wallet.objects.first().private_key)

        deploy.call_contract_function(dao_contract.functions.propose,
                                      asc_address,
                                      private_key=Wallet.objects.first().private_key)

        asc.blockchain_state = BlockchainState.COMPLETED
        asc.address = asc_address
        asc.save()
Example #7
0
def create_project(self, project_id: int) -> None:
    # TODO add mechanism to retry if anything in here fails
    # TODO there's lots of opportunity for failure in this function, we should be
    # more resilient

    logger.info(f'Attempting to get lock to create project {project_id}')

    # TODO extend to support locking based on wallets
    with REDIS_CLIENT.lock('create-project'):
        logger.info(f'Acquired lock to create project {project_id}')
        project = Project.objects.get(pk=project_id)

        project.blockchain_state = BlockchainState.STARTED.value
        project.save()

        compiler = ContractCompiler()
        mycro_project = Project.get_mycro_dao()

        w3 = deploy.get_w3()

        contract_interface = compiler.get_contract_interface('mycro.sol',
                                                             'MycroCoin')
        mycro_contract = w3.eth.contract(abi=contract_interface['abi'],
                                         address=mycro_project.dao_address)

        base_dao_interface = compiler.get_contract_interface('base_dao.sol',
                                                             'BaseDao')
        merge_module_interface = compiler.get_contract_interface(
            'merge_module.sol', 'MergeModule')

        creators = []
        creator_balances = []
        logger.info(f'Project balances are {project.initial_balances}')
        for creator, balance in project.initial_balances.items():
            creators.append(creator)
            creator_balances.append(balance)

        total_supply = sum(creator_balances)

        # TODO add validation of project properties
        w3, dao_contract, dao_address, _ = deploy.deploy(base_dao_interface,
                                                         project.symbol,
                                                         project.repo_name,
                                                         project.decimals,
                                                         total_supply,
                                                         creators,
                                                         creator_balances,
                                                         private_key=Wallet.objects.first().private_key)

        _, _, merge_module_address, _ = deploy.deploy(merge_module_interface,
                                                      private_key=Wallet.objects.first().private_key)

        deploy.call_contract_function(
            dao_contract.functions.registerModule,
            merge_module_address,
            private_key=Wallet.objects.first().private_key)
        deploy.call_contract_function(
            mycro_contract.functions.registerProject,
            dao_address,
            private_key=Wallet.objects.first().private_key)


        project.blockchain_state = BlockchainState.COMPLETED.value
        project.dao_address = dao_address
        project.merge_module_address = merge_module_address
        project.save()

        github.create_repo(repo_name=project.repo_name,
                           organization=settings.github_organization())

    logger.info(f'Finished creating project {project_id}')
Example #8
0
    # the lowest ID as the main wallet of this application
    if not Wallet.objects.filter():
        account = w3.eth.account.create('')
        private_key = account.privateKey.hex()
        Wallet.objects.create(private_key=private_key, address=account.address)

    # if the wallet isn't funded, fund it
    main_wallet = Wallet.objects.first()
    deploy.fund_account_if_needed(w3, settings.ethereum_private_key(),
                                  main_wallet.private_key)

    # TODO remove this when we no longer need to deploy the mycro contract on init
    # maybe we should hide this behind an env variable because this is useful for testing
    mycro_project = Project.objects.filter(is_mycro_dao=True)
    if len(mycro_project) == 0:
        compiler = ContractCompiler()
        _, mycro_contract, mycro_address, mycro_instance = deploy.deploy(
            compiler.get_contract_interface('mycro.sol', 'MycroCoin'),
            private_key=main_wallet.private_key,
            timeout=None)
        Project.create_mycro_dao(mycro_address,
                                 symbol=mycro_instance.symbol(),
                                 decimals=mycro_instance.decimals())
    elif len(mycro_project) > 1:
        raise ValueError("Shit there are two mycro DAOs")

    # Set up background tasks which monitor blockchain for events
    schedule, created = IntervalSchedule.objects.get_or_create(
        every=5,
        period=IntervalSchedule.SECONDS,
    )
Example #9
0
    w3 = deploy.get_w3()

    # If no wallet exists in the db create it. If one exists, treat the one with
    # the lowest ID as the main wallet of this application
    if not Wallet.objects.filter():
        account = w3.eth.account.create('')
        private_key = account.privateKey.hex()
        Wallet.objects.create(private_key=private_key, address=account.address)

    # if the wallet isn't funded, fund it
    main_wallet = Wallet.objects.first()
    deploy.fund_account_if_needed(w3, settings.ethereum_private_key(), main_wallet.private_key)

    # TODO remove this when we no longer need to deploy the mycro contract on init
    # maybe we should hide this behind an env variable because this is useful for testing
    mycro_project = Project.objects.filter(is_mycro_dao=True)
    if len(mycro_project) == 0:
        compiler = ContractCompiler()
        _, mycro_contract, mycro_address, mycro_instance = deploy.deploy(
            compiler.get_contract_interface('mycro.sol', 'MycroCoin'), private_key=main_wallet.private_key, timeout=None)
        Project.create_mycro_dao(mycro_address, symbol=mycro_instance.symbol(), decimals=mycro_instance.decimals())
    elif len(mycro_project) > 1:
        raise ValueError("Shit there are two mycro DAOs")

    # Set up background tasks which monitor blockchain for events
    schedule, created = IntervalSchedule.objects.get_or_create(every=5, period=IntervalSchedule.SECONDS, )
    if not PeriodicTask.objects.filter(name=MERGE_PR_BEAT_NAME):
        PeriodicTask.objects.create(interval=schedule, name=MERGE_PR_BEAT_NAME,
                                    task='backend.server.tasks.process_merges')

Example #10
0
from backend.server.utils.contract_compiler import ContractCompiler
from web3 import Web3, Account
from web3.providers.eth_tester import EthereumTesterProvider
from eth_tester import EthereumTester
import backend.constants as app_constants

COMPILER = ContractCompiler()
TESTER = EthereumTester()
TESTER.add_account(app_constants.DEFAULT_ETHEREUM_PRIVATE_KEY)
W3 = Web3(EthereumTesterProvider(ethereum_tester=TESTER))

TESTER.send_transaction({
    'from': W3.eth.accounts[0],
    'to': app_constants.DEFAULT_ETHEREUM_ADDRESS,
    'gas': 21000,
    'value': int(10e18)
})

# hardcoded Ethereum addresses
PROJECT_ADDRESS = '0x1111111111111111111111111111111111111111'
REWARDEE = '0x1111111111111111111111111111111111111112'
MYCRO_ADDRESS = '0x1111111111111111111111111111111111111113'
INITIAL_ADDRESS = '0x1111111111111111111111111111111111111114'
ASC_ADDRESS = '0x1111111111111111111111111111111111111115'

MYCRO_PROJECT_NAME = 'mycro'
MYCRO_PROJECT_SYMBOL = 'myc'
PROJECT_NAME = 'foobar'
PROJECT_SYMBOL = PROJECT_NAME[:3]
GITHUB_ACCESS_TOKEN = 'fake'
GITHUB_ORGANIZATION = 'lolwut'