ape
ape copied to clipboard
Export Solidity functions as Python functions
Overview
I want to generate Python functions from a smart contract's ABI definitions.
Specification
I would expect this to be part of the ape.contracts package.
Dependencies
For reference, I found some (old) implementations that don't actually do what I'm thinking. https://github.com/Consensys/python-solidity-parser/tree/master (last commit 3 years ago)
This also goes in the right direction -> https://github.com/ethereum/web3.py/issues/3016
This would take a larger refactor to move to a more functional, metaclass-style method for generating ContractContainer singleton classes from ethpm_types.ContractType models which can be instantiated (and enhanced with other information from ContractType such as NatSpec docs, etc.)
@BobTheBuidler might find this idea interesting, he was looking for a way to avoid having multiple instances of ContractType models to reduce the memory usage of Ape with large amounts of instances with the same contract type
cc @antazoey @bitwise-constructs who are thinking about overall improvements to contract ergonomics
I just want to have some things to visualize for us to discuss, as this might be something we want to consider for 0.9.
Currently:
>>> from ape import project
>>> project.MyContract
Note: currently, all contract-types are the same class and not individual classes (not generated at runtime via ABI)
Proposition:
>>> from ape.contracts import MyContract
The new MyContract is something generated at runtime via the ABI. All methods are readidly available. Structs are the same, we already use meta-classes for those, same with errors.
^ That last sentence is a good point: we are already using metaclass / runtime type generation for errors and structs, so one more step to ContractType feels right.
Anyway, the downside is the metaclass are weird, but I think one can just expect that... like you can't use issubclass and some other stuff like that.
Proposition:
>>> from ape.contracts import MyContract
As an overall note, this level of change (migrating from using ape.project.MyContract to ape.contracts.MyContract) would be a v1.0 type of breaking change
Further, I don't think I like automatically generating imports. That's what Brownie used to do, and it's very difficult because you pollute the namespace of the module. It can be much more simple that project.__getattr__ uses keys from the current project's known contract types and generates custom classes using ContractContainer more as a metaclass (or we can get rid of ContractContainer entirely). Still, like you said it would be a breaking change to remove ContractContainer from the class heirarchy (and ContractInstance, which subclasses ape.api.address.BaseAddress) but there are ways of just applying a common parent class when forming the metaclass to maintain that heirarchy for all the generated subclasses.
In a similar vein, we can probably do the same with MethodABI objects to generate custom method handlers as metaclasses and insert them into the ContractInstance objects (closer to what this issue's OP is talking about) This might also be a breaking v1.0 level change due to the change of metaclasses, type annotation support, etc. (I think I am using ContractMethodHandler inside of ape-safe and the multicall module)