ApeWorX / ape

The smart contract development tool for Pythonistas, Data Scientists, and Security Professionals
https://apeworx.io
Apache License 2.0
866 stars 133 forks source link

Allow Plugins to customize ContractContainer and ContractType #818

Closed antazoey closed 10 months ago

antazoey commented 2 years ago

Elevator pitch:

Deploying contracts and / or contract interaction can sometimes work differently, depending on the development environment (e.g. Starknet)

ape-starknet needs more customization around ContractContainers available on the ProjectManager (e.g. ape.project.MyContract).

We need to support contract declaration. Soon, Deploy transactions will no longer work on Starknet. A contract declaration in Starknet is a type of transaction (like a Deploy) but for allowing other contracts to deploy your contract. You cannot invoke methods on a ContractDeclaration. It like a Class versus an instance of the class. In Starknet, you publish your contract types and other contracts (accounts) can deploy those types.

Additionally, we would like to be able to customize the selector hash function of contract types, which is available in ethpm-types but there is not an easy way to force Ape to use a custom class of ContractType.

Value:

Dependencies:

n/a

Design approach:

ape.api.compilers.py:

class CompilerAPI:
    contract_type_cls: Type[ContracType] = ContractType
    """The class to use when creating contract types."""

CompilerManager in ape:

class CompilerManager:
    def lookup_contract_type_cls(self, contract_type):
        """Get the plugin defined contract type cls for a given contract type."""

new file: ape.api.contracts.py:

class ContractContainerAPI:
   @abstractmethod
   def is_container_type(self, contract_type: ContractType):
        ...

   @abstractmethod
   def get_container(self, contract_type) -> ContractContainer:
        ....

class ContractContainer:
   def is_container_type(self, contract_type: ContractType):
       """Return True when the contract type is part of a specific plugin's container type."""

   def get_container(self, contract_type) -> ContractContainer:
        plugin_defined_contract_type = self.compiler_manager.lookup_contract_type_cls(contract_type)
        return ContractContainer(plugin_defined_contract_type)

ape-cairo compilers.py:

class StarknetContractType(ContractType):
    """A contract type with a custom hash function using the Starknet keccak
         for easy lookup of contract methods."""

class CairoCompiler:
    contract_type_cls = StarknetContractType

ape-starknet register the container

from ape.api.contracts import ContractContainer

# Has all the same methods as the normal container except adding new ones (still a registerable API class)
class StarknetContractContainer(ContractContainer):
    def declare() -> ContractDelcaration (definiton TBD)

Task list:

Estimated completion date:

For now, the plan to add declare() to the accounts, since we have deploy() there as well. However, it is more ideal to have both.

Design review:

Do not signoff unless:

(Please leave a comment to sign off)

Related Tickets

Contract declaration support: https://github.com/ApeWorX/ape-starknet/issues/32 Custom selector insurance: https://github.com/ApeWorX/ethpm-types/issues/38 Custom contract types in ape-cairo: https://github.com/ApeWorX/ape-cairo/issues/20

antazoey commented 2 years ago

This is also something that is hinting might be a good ticket to do for titanboa enhancement.

My idea is something along the lines of allowing ape-vyper to customize ContractContainer objects for vyper contracts. I don't know exactly how that will work yet.

@fubuloubu

antazoey commented 10 months ago

No longer needed - declare is now part of official API.