def test_deploy_eth_contract(self):
        log = logging.getLogger("SidechainEthTest")
        with mock_server(SidechainEth) as stub:
            filename = 'test/HelloWorld.sol'
            with open(filename, 'r') as myfile:
                contract_source = myfile.read()
            contract_metadata = parser.parse_file(filename)
            contract_name = contract_metadata['children'][1]['name']
            
            jwt_info = {
                'network': self.network,
                'eth_account_address': self.ela_eth_to_use,
                'eth_private_key': '0x35a12175385b24b2f906d6027d440aac7bd31e1097311fa8e3cf21ceac7c4809',
                'eth_gas': 2000000,
                'contract_source': contract_source,
                'contract_name': contract_name,
            }

            jwt_token = jwt.encode({
                'jwt_info': jwt_info,
                'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=settings.TOKEN_EXPIRATION)
            }, self.api_key_to_use, algorithm='HS256')

            response = stub.DeployEthContract(sidechain_eth_pb2.Request(input=jwt_token), timeout=settings.REQUEST_TIMEOUT, metadata=[('did', self.did_to_use)])
            log.debug(f"Method: test_deploy_eth_contract, Expected: True, Actual: {response.status}")
            self.assertEqual(response.status, True)
예제 #2
0
def run(): 
    from solidity_parser import symbolic, parser
    asttree = parser.parse_file("BookStore.sol")
    f = open("renderToPython.py", 'w')
    f.write(open('init.py').read())
    f.close()
    f = open("renderToPython.py", 'a+')
    dse = symbolic.SymbolicExecution(asttree,f )
    listFunc= dse.run()
    f.close()
    import renderToPython
    transaction = renderToPython.BookStore()
    init = ('0xAAAA',
        (renderToPython.ownerToBalance['0xAAAA'], 
        renderToPython.getSumToken(renderToPython.totalToken)), 

            '0xBBBB',
        (renderToPython.ownerToBalance['0xBBBB']+renderToPython.msg.value,
        renderToPython.getSumToken(renderToPython.ownerToOrderList['0xBBBB']) ))
    transaction.implementTransaction('0xBBBB', 'mathematic', 1 )
    final = ('0xAAAA',(renderToPython.ownerToBalance['0xAAAA'], 
            renderToPython.getSumToken(renderToPython.totalToken)), 
            '0xBBBB',(renderToPython.ownerToBalance['0xBBBB'],
            renderToPython.getSumToken(renderToPython.ownerToOrderList['0xBBBB']) ))
    return init, final
예제 #3
0
def parse_file(filepath: Path) -> dict:
    """ Parse a file using solidity_parser

    :param filepath: (:code:`str` or :class:`pathlib.Path`) Path to the source file to check
    :returns: (:code:`dict`) A Python dict representation of the source file
    """
    return parser.parse_file(str(filepath))
예제 #4
0
def check_solidity_version(url):
    """Check if a repository is a fix repository by checking if it contains atleast one file with version >=0.4.19

    :param url: URL of repository
    :return: True if repository is a fix repo else False
    """
    # clone repo
    path = os.getcwd() + '/data'
    if not os.path.exists(path):
        os.mkdir('data')

    # check if repo has .sol files or not
    response = make_request(url + '/search?q=extension%3Asol', HEADER)
    parsed = BeautifulSoup(response.content, 'html.parser')
    try:
        parsed.find('div', class_='code-list').find('a')['href']
    except Exception as e:
        logging.exception(e)
        logging.info('Does not contains .sol files')
        return False, '0'

    if not clone_repo(url, path):
        return False, '0'

    sol_files = get_sol_files(path + '/' + url.split('/')[-1])

    for sol_file in sol_files:
        try:
            parsed = parser.parse_file(sol_file)
            ver = None
            for child in parsed['children']:
                if child['type'] == 'PragmaDirective':
                    ver = child['value']
                    break
            # ver = parsed['children'][0]['value'].replace('^','')

            if not ver:
                logging.error('File version not found in file ' +
                              str(sol_file))
                continue

            ver = ver.replace('^', '')
            if '<' in ver:
                ver = ver.split('<')[0]
            file_sol_ver = semantic_version.SimpleSpec(ver)

            # checking if version >= 0.4.19
            req_sol_ver = semantic_version.SimpleSpec('>=0.4.19')
            if req_sol_ver.match(file_sol_ver.clause.target):
                shutil.rmtree(path + '/' + url.split('/')[-1])
                return True, len(sol_files)

        except Exception as e:
            logging.exception(e)
            continue

    # delete cloned copy of repo
    shutil.rmtree(path + '/' + url.split('/')[-1])
    return False, '0'
예제 #5
0
def runSC(admin, user_address, ownerToOrderList, ownerToBalance, totalToken,
          book_isbn, book_quantity, book_price):
    # cần build msg
    from solidity_parser import symbolic, parser
    import collections
    asttree = parser.parse_file("BookStore.sol")
    f = open("renderToPython.py", 'w')
    f.write(open('init.py').read())
    f_write(f, 'admin', admin, 'str')
    f_write(f, 'user_address', user_address, 'str')
    f_write(f, 'totalToken', totalToken, 'dict')
    f.write("ownerToOrderList = collections.defaultdict(lambda : 0)\n")
    f_write(f, "ownerToOrderList[user_address]",
            ownerToOrderList[user_address], 'dict')
    f.write(
        "ownerToOrderList[user_address]=convert(ownerToOrderList[user_address])\n"
    )
    f.write("ownerToBalance= collections.defaultdict(lambda : 0)\n")
    f_write(f, "ownerToBalance[admin]", ownerToBalance[admin], 'number')
    f_write(f, "ownerToBalance[user_address]", ownerToBalance[user_address],
            'number')
    f_write(f, "ownerToBalance['0xcAd4954fA4cb431bAD9a84c3ae8e279fe069A6De']",
            ownerToBalance['0xcAd4954fA4cb431bAD9a84c3ae8e279fe069A6De'],
            'number')
    f_write(f, "book_quantity", book_quantity, 'number')
    f_write(f, "book_price", book_price, 'number')
    f_write(f, "book_isbn", book_isbn, 'str')
    f.write("msg = Msg(admin, user_address, book_price*book_quantity)\n")
    f.write("ownerToBalance['0x0000'] = msg.value\n")
    f.close()
    f = open("renderToPython.py", 'a+')
    dse = symbolic.SymbolicExecution(asttree, f)
    listFunc = dse.run()
    f.close()

    import renderToPython
    transaction = renderToPython.BookStore()
    init = (
        renderToPython.admin,
        (renderToPython.ownerToBalance[renderToPython.admin],
         renderToPython.getSumToken(renderToPython.totalToken)),
        renderToPython.user_address,
        (renderToPython.ownerToBalance[renderToPython.user_address] +
         renderToPython.msg.value,
         renderToPython.getSumToken(
             renderToPython.ownerToOrderList[renderToPython.user_address])))
    transaction.implementTransaction(user_address, book_isbn, book_quantity)
    final = (
        renderToPython.admin,
        (renderToPython.ownerToBalance[renderToPython.admin],
         renderToPython.getSumToken(renderToPython.totalToken)),
        renderToPython.user_address,
        (renderToPython.ownerToBalance[renderToPython.user_address],
         renderToPython.getSumToken(
             renderToPython.ownerToOrderList[renderToPython.user_address])))

    return init, final
예제 #6
0
    def convert_to_ast(self):
        """ 
        Break down Solidity Contract into an AST object.
        """
        try:
            self.source_unit = parser.parse_file(self.file_path)

            # Subparse AST into objects for nicer interfaces: Create a nested
            # object structure from AST
            self.source_unit_object = parser.objectify(self.source_unit)
        except AttributeError:
            self.status = 'invalid'
예제 #7
0
    def deploy_eth_contract(self, api_key, did, network, eth_account_address,
                            eth_private_key, eth_gas, filename):
        with open(filename, 'r') as myfile:
            contract_source = myfile.read()
        contract_metadata = parser.parse_file(filename)
        contract_name = contract_metadata['children'][1]['name']

        jwt_info = {
            'network': network,
            'eth_account_address': eth_account_address,
            'eth_private_key': eth_private_key,
            'eth_gas': eth_gas,
            'contract_source': contract_source,
            'contract_name': contract_name,
        }

        jwt_token = jwt.encode(
            {
                'jwt_info':
                jwt_info,
                'exp':
                datetime.datetime.utcnow() +
                datetime.timedelta(hours=TOKEN_EXPIRATION)
            },
            api_key,
            algorithm='HS256')

        response = self.stub.DeployEthContract(
            sidechain_eth_pb2.Request(input=jwt_token),
            timeout=REQUEST_TIMEOUT,
            metadata=[('did', did)])

        if response.status:
            output = jwt.decode(response.output,
                                key=api_key,
                                algorithms=['HS256']).get('jwt_info')
            result = {
                'output': json.dumps(output),
                'status_message': response.status_message,
                'status': response.status
            }
            return result
        else:
            result = {
                'output': '',
                'status_message': response.status_message,
                'status': response.status
            }
            return result
예제 #8
0
import sys
import pprint

from solidity_parser import parser

sourceUnit = parser.parse_file(sys.argv[1])
#pprint.pprint(sourceUnit)

sourceUnitObject = parser.objectify(sourceUnit)

# access imports, contracts, functions, ...  (see outline example in
# __main__.py)
sourceUnitObject.imports  # []
sourceUnitObject.pragmas  # []
for contract_name in sourceUnitObject.contracts.keys():
    print(contract_name)
예제 #9
0
def create_log_contract(input_filename, output_filename):   
    sourceUnit = parser.parse_file(input_filename)

    pragma = ""
    for child in sourceUnit["children"]:

        # Get the pragma version
        # It should always be the first line near the top before the contract definitions
        if child["type"] == "PragmaDirective":

            pragma = "pragma solidity " +  child['value'] + ";\n"
        
        elif child["type"] == "ContractDefinition":
            subnodes = child['subNodes']
            statevariables = dict()
            contractName = child['name'] + "Log"

            for node in subnodes:   
                nodetype = node['type']

                # Get all the state variables
                # If it is an address, make note of it it is payable
                if nodetype == 'StateVariableDeclaration':
                    for variable in node['variables']:
                        if variable['visibility'] == 'public':
                            # At the moment, this framework will only work on state variables that are of type : ElementaryTypeName
                            if variable['typeName']['type'] == "ElementaryTypeName":
                                statevariables[variable['name']] = variable["typeName"]["name"]
            
            # Write the log contract
            f = open(output_filename, "w")
            f.write(pragma)
            f.write("contract " + contractName + " {\n")

            for variable in statevariables:
                variabletype = statevariables[variable]
                f.write("\t" + variabletype + " public " + variable + ";\n")

            constructor = "constructor ("
            idx = 0
            for variable in statevariables:
                if idx > 0:
                    constructor += ","
                variabletype = statevariables[variable]
                if variabletype == "string":
                    constructor += variabletype + " memory _" + variable
                else:
                    constructor += variabletype + " _" + variable
                idx += 1

            constructor += ") public {\n"
            for pair in sorted(statevariables.items()):
                variable = pair[0]
                constructor += variable + " = _" + variable + ";\n"
            constructor += "}\n"
            f.write(constructor)

            # Fallback function
            # f.write("function () public payable {}\n")

            for variable in statevariables:
                variabletype = statevariables[variable]
                function = "function update" + variable + " ("
                if variabletype == "string":
                    function += variabletype + " memory _" + variable
                else:
                    function += variabletype + " _" + variable
                function += ") public {\n"
                function += "\t" + variable + " = _" + variable + ";\n"

                function += "}\n"
                f.write(function)
            
            f.write("}")
            f.close()
예제 #10
0
def apply_CDTF(input_filename, output_filename, logfilename):
    sourceUnit = parser.parse_file(input_filename)
    f = open(input_filename, "r")
    contract = f.read()
    f.close()
    

    operator_signs = ["+", "-", "*", "/"]
  
    for child in sourceUnit["children"]:
        
        if child["type"] == "ContractDefinition":
            subnodes = child['subNodes']
            statevariables = dict()
            contractName = child['name']
            contractLogTypeName = contractName + "Log"
            contractLogVariableName = contractLogTypeName + "logs"

            functions_to_modify = []
            cdtf_enter_re = r"@CDTF\s+ENTER\s*function.+\(.*\).*{"
            cdtf_end_re = r"@CDTF\s+END\s*function.+\(.*\).*{"

            for node in subnodes:   
                nodetype = node['type']

                # Get all the state variables
                # If it is an address, make note of it it is payable
                if nodetype == 'StateVariableDeclaration':
                    for variable in node['variables']:
                        if variable['visibility'] == 'public':
                            # At the moment, this framework will only work on state variables that are of type : ElementaryTypeName
                            if variable['typeName']['type'] == "ElementaryTypeName":
                                statevariables[variable['name']] = variable["typeName"]["name"]

                elif nodetype == "FunctionDefinition" and not node['isConstructor']:
                    
                    name = node['name']
                    definition_re = r"@CDTF\s*function\s+" + name + r"\s*\(.*\).*{"
                    functionDefinitionresult = re.search(definition_re, contract)
                    if functionDefinitionresult is None:
                        # Check for the ENTER tag
                        definition_re = r"@CDTF\s+ENTER\s*function\s+" + name + r"\s*\(.*\).*{"
                        functionDefinitionresult = re.search(definition_re, contract)
                        if functionDefinitionresult is None:
                            definition_re = r"@CDTF\s+END\s*function\s+" + name + r"\s*\(.*\).*{"
                            functionDefinitionresult = re.search(definition_re, contract)

                            if functionDefinitionresult is None:
                                continue
                            else:
                                cdtf_end_re = definition_re
                        else:
                            cdtf_enter_re = definition_re

                    functions_to_modify.append(definition_re)


            if len(logfilename) < 2 or logfilename[:2] != "./":
                logfilename = "./" + logfilename
            import_statement = "import \"" + logfilename + "\";"
            # Create the instance variable
            logs_var = contractLogTypeName + " private " + contractLogVariableName + ";"    

            # Insert this at the very start of the contract
            contractdefinition = r"contract\s+" + contractName + r".*{"
            contractdefinitionResult = re.search(contractdefinition, contract).group()
            # Add the contract log 
            contract = re.sub(contractdefinitionResult, import_statement + "\n" + contractdefinitionResult + "\n" + logs_var + "\n", contract)


            cdtf_enter = re.search(cdtf_enter_re, contract)
            cdtf_end = re.search(cdtf_end_re, contract)
            if cdtf_enter is None or cdtf_end is None:
                # There is no cdtf entrance
                continue

            
            
            # For every place that contains  @CDTF tag, replce all variable assignemnts and reads to Log updates and reads
            for func_def in functions_to_modify:
                # First, replace all +=, -=, /=, and *=
                new_func_def = find_function(contract, func_def)
                original_function = new_func_def
                for var in statevariables:
                    for sign in operator_signs:
                        var_re = var + r"\s*[" + sign + r"]="
                        new_update_statement = var + " = " + var + " " + sign + " "
                        new_func_def = re.sub(var_re, new_update_statement, new_func_def)
                
                
                # Next, replace all assignment statements with a call to the update function in the log
                for var in statevariables:
                    var_assignment_re = var + r"\s*="
                    var_assignment_re_result = re.search(var_assignment_re, new_func_def)
                    if var_assignment_re_result is not None:
                        new_update_statement = contractLogVariableName + ".update" + var + "("
                        new_func_def = new_func_def.replace(var_assignment_re_result.group(), new_update_statement )

                        # Add the ending parenthesis
                        var_update_re = r"(?<=" + contractLogVariableName + ".update" + var + r"\().*;"
                        
                        update_parameters = re.findall(var_update_re, new_func_def)

                        for result in update_parameters:
                            update_parameter_modified = new_update_statement + result[:-1] + ");"

                            new_func_def = new_func_def.replace(new_update_statement + result,  update_parameter_modified) 

                # Finally, replace all remaining uses of the state variable to calls to the log function

                for var in statevariables:
                    log_read_statement = contractLogVariableName + "." + var + "() "
                    variable_re = r"[^0-9A-Fa-f]" + var + r"[^0-9A-Fa-f]"
                    variable_results = re.findall(variable_re, new_func_def)
                    for result in variable_results:
                        newresult = result.replace(var, log_read_statement)

                        new_func_def = new_func_def.replace(result, newresult)


                contract = contract.replace(original_function, new_func_def)


            # Find the @CDTF ENTER tag. That indicates where to create the log contract
            contract_creation = contractLogVariableName + " = new " + contractLogTypeName + "(" 
            first = True
            for var in statevariables:
                if not first:
                    contract_creation += ","
                else:
                    first = False
                contract_creation += var

            contract_creation += ");"
            contract = re.sub(cdtf_enter_re, cdtf_enter.group() + "\n" + contract_creation + "\n", contract)
            
            # Find the @CDTF END tag. This indicates at the end, you need to update the contract
            contract_update = ""
            for var in statevariables:
                contract_update += var + " = " + contractLogVariableName + "." + var + "();\n"
            ending_function = find_function(contract, cdtf_end_re)
            new_ending_function = ending_function[:-1] + "\n" + contract_update + "\n}"
            contract = contract.replace(ending_function, new_ending_function)


    # Write the new contract into a file
    f = open(output_filename, "w")
    f.write(contract)
    f.close
예제 #11
0
 def parse_contract(self):
     self.parsed_contract = parser.parse_file(self.contract_path)
예제 #12
0
def main():
	global currentcontractobject
	global spaces

	parsedtree = parser.parse_file("samplecontract.sol")  # Contracts written in local file
	parsedtreeobject = parser.objectify(parsedtree)
	pprint.pprint(parsedtree)
	all_contracts_names = parsedtreeobject.contracts.keys()  # get all contract names
	all_contracts_names = list(all_contracts_names)

	for contract_name in all_contracts_names:

		print(f"\n\n-------------------\tInformation of Contract: {contract_name}\t-------------------\n")
		currentcontractobject = parsedtreeobject.contracts[contract_name]
		state_variables_names = list(parsedtreeobject.contracts[contract_name].stateVars.keys())
		print(f"All State Variables Are:\n{state_variables_names}")

		global metaarray
		metaarray = []
		storage_index = 0
		byte_index = 0

		for variable_name in state_variables_names:
			print("Storage Index: " + str(storage_index))
			varprops = []
			print(f"\n\n{spaces}Properties of a Variable:\n\n{spaces}Name:\t\t\t{variable_name}")
			statevariableobject = parsedtreeobject.contracts[contract_name].stateVars[variable_name]
			varprops.append(statevariableobject['typeName']['type'])
			varprops.append(variable_name)

			if statevariableobject['typeName']['type'] == 'ElementaryTypeName':
				variable_type = statevariableobject['typeName']['name']
				varprops.append(variable_type)
				storage_index, byte_index, v2 = elementaryvariables(statevariableobject, variable_type,
				                                                    storage_index, byte_index)
				varprops = varprops + v2

				metaarray.append(varprops)
				continue

			if statevariableobject['typeName']['type'] == 'UserDefinedTypeName':
				# Check if struct
				if statevariableobject['typeName']['namePath'] in list(
						parsedtreeobject.contracts[contract_name].structs.keys()):

					variable_type = statevariableobject['typeName']['namePath']
					varprops.append(variable_type)

					storage_index, byte_index, v2 = structs(statevariableobject, variable_type, storage_index,
					                                        byte_index)
					varprops = varprops + v2
					metaarray.append(varprops)
					continue

				if statevariableobject['typeName']['namePath'] in list(
						parsedtreeobject.contracts[contract_name].enums.keys()):
					variable_type = statevariableobject['typeName']['namePath']
					varprops.append(variable_type)
					storage_index, byte_index, v2 = enums(statevariableobject, variable_type, storage_index, byte_index)
					varprops = varprops + v2
					metaarray.append(varprops)
					continue

			if statevariableobject['typeName']['type'] == 'ArrayTypeName':
				storage_index, byte_index, v2 = arraytype(statevariableobject, storage_index, byte_index)
				varprops = varprops + v2
				metaarray.append(varprops)
				continue

			if statevariableobject['typeName']['type'] == 'Mapping':
				variable_name = statevariableobject['name']
				keytype = statevariableobject['typeName']['keyType']['name']
				if statevariableobject['typeName']['valueType']['type'] == 'ElementaryTypeName':
					valuetype = statevariableobject['typeName']['valueType']['name']
				else:
					valuetype = statevariableobject['typeName']['valueType']['namePath']
				st = str(keytype) + "=>" + str(valuetype)
				varprops.append(st)
				if byte_index != 0:
					storage_index += 1
				byte_index = 0
				print(f"{spaces}Key Type:\t\t{keytype}\n\tValue Type:\t\t"
				      f"{valuetype}\n\tIndex Assigned:\t{storage_index}")
				varprops.append(storage_index)
				varprops.append(None)
				varprops.append(32)
				storage_index += 1
				metaarray.append(varprops)
				continue

			print(f"{spaces}The State Variable given is of Unhandled Type. Type:"
			      f" {statevariableobject['typeName']['type']}")
			break

		print("\n\n==================================================================\nGeneral:\tVariable Type | Name | "
		      "Data "
		      "Type | Storage Index | Byte Index | Size\nArrays:\t\tVariable Type | Name | Data "
		      "Type | [ 1st Packed Patch: [Storage Index | Byte Index | Size], ...]\n\n")
		for row in metaarray:
			print(row)
예제 #13
0
def apply_SDTF(input_filename, output_filename):
    # This script will append on additional parameters to each SDTF marked function.
    # The variable names will equal {variable_prefix}_{state variable name}
    # The new parameters will be added to the front of the parameter list and in alphabetical order
    # Only function definitions that are immediately proceded by the tag @STDF in a comment will be considered
    sourceUnit = parser.parse_file(input_filename)

    f = open(input_filename, "r")
    contract = f.read()
    f.close()

    variable_prefix = "readset"

    for child in sourceUnit["children"]:
        # If there is more than one contract definition within this file, then this script
        # assumes that every function between the two contracts has a different name

        if child["type"] == "ContractDefinition":
            subnodes = child['subNodes']

            statevariables = dict()

            # Iterate once through to grab all the statevariables
            for node in subnodes:
                nodetype = node['type']
                if nodetype == 'StateVariableDeclaration':
                    for variable in node['variables']:
                        if variable['visibility'] == 'public':
                            # At the moment, this framework will only work on state variables that are of type : ElementaryTypeName
                            if variable['typeName'][
                                    'type'] == "ElementaryTypeName":
                                statevariables[variable['name']] = variable[
                                    "typeName"]["name"]

            # Iterate again to examine each function definition
            for node in subnodes:
                nodetype = node['type']
                if nodetype == "FunctionDefinition" and not node[
                        'isConstructor']:
                    # Identify all the statevariables that are used in each function
                    body = node['body']
                    name = node['name']
                    used_state_variables = list(
                        extract_state_variables(body, statevariables.keys()))
                    used_state_variables.sort()
                    if len(used_state_variables) > 0:

                        # First, get the list of parameters
                        definition_re = r"@SDTF\s*function\s+" + name + r"\("
                        functiondefinitionResult = re.search(
                            definition_re, contract)
                        if functiondefinitionResult is None:
                            continue

                        functiondefinition = functiondefinitionResult.group()

                        # Create the require statement and updated parameter list
                        requires = "require("
                        for idx, variable in enumerate(used_state_variables):
                            if idx > 0:
                                requires += " && "
                                functiondefinition += ","
                            requires += variable + " == " + variable_prefix + "_" + variable
                            functiondefinition += statevariables[
                                variable] + " " + variable_prefix + "_" + variable

                        requires += ", \"Readset of contract data at time of calling is stale\");"

                        # Append parameters to this function.
                        # Also check if there are any parameters in this function already. If so, then you will need to append a comma to the end of the new functiondefinition
                        if len(node['parameters']['parameters']) > 0:
                            functiondefinition += ","

                        # Add the requires statement
                        old_definition = re.search(
                            r"function\s+" + name + r"\(.*\).*\{",
                            contract).group()
                        contract = re.sub(
                            r"function\s+" + name + r"\(.*\).*\{",
                            old_definition + "\n" + requires + "\n", contract)

                        # Update the parameter list
                        contract = re.sub(definition_re, functiondefinition,
                                          contract)

    # Write the new contract into a file
    f = open(output_filename, "w")
    f.write(contract)
    f.close
예제 #14
0
    cwd = os.getcwd()
    os.system(
        f"cd {repo} && node ./node_modules/.bin/prettier --write {target} --config .prettierrc && cd {cwd}"
    )


arg_parser = argparse.ArgumentParser(
    description=
    "Generates Solidity rich reverts library and corresponding Typescript classes from boilerplate."
)
arg_parser.add_argument("--repo", help="Absolute path to monorepo.")
arg_parser.add_argument(
    "--lib_path",
    help=
    "Path (relative to monorepo) to Solidity file containing library boilerplate.",
)

args = arg_parser.parse_args()

sol_target = f"{args.repo}/{args.lib_path}"
ts_target = get_ts_target(args.repo, args.lib_path)

sourceUnit = parser.parse_file(sol_target)
sourceUnitObject = parser.objectify(sourceUnit)
contractName = list(sourceUnitObject.contracts.keys())[0]
contractObject = sourceUnitObject.contracts[contractName]

sol_codegen(contractName, contractObject, sol_target)
ts_codegen(contractObject, args.repo, ts_target)