As vyper is evolving, a lot of new exciting changes have been introduced in version 0.4.0
. Today, we are going to put our focus on two built-in functions: initializes
and exports
.
initializes
This mainly is useful when you need to initialize a module's state.
exports
In Vyper, @external
functions are not automatically exposed (i.e., included in the runtime code) in the importing contract. This means that any externally facing functionality must be explicitly defined in the top-level of the compilation target.
So, exporting external functions from modules is accomplished using the exports
keyword.
Anyway, to better understand these, we shall use a code example.
I am going to illustrate using three contracts i.e A.vy
, B.vy
and C.vy
where A.vy
is the module we gonna be utilizing.
A.vy
#pragma version >0.3.10 x: public(uint256) y: public(uint256) z: public(uint256) @deploy def __init__(_x: uint256, _y: uint256): self.x = _x self.y = _y @external def add(_x: uint256, _y: uint256): self._add(_x, _y) @internal def _add(_x: uint256, _y: uint256): _z: uint256 = _x + _y self.z = _z
B.vy
#pragma version >0.3.10 from . import A initializes: A @deploy def __init__(_x: uint256, _y: uint256): A.__init__(_x, _y) @external def set_value(_x: uint256, _y: uint256): A._add(_x, _y) @view @external def get_x() -> uint256: _x: uint256 = A.x return _x @view @external def get_y() -> uint256: _y: uint256 = A.y return _y @view @external def get_z() -> uint256: result: uint256 = A.z return result
C.vy
#pragma version >0.3.10 from . import A initializes: A exports: A.add @deploy def __init__(_x: uint256, _y: uint256): A.__init__(_x, _y) @view @external def get_x() -> uint256: _x: uint256 = A.x return _x @view @external def get_y() -> uint256: _y: uint256 = A.y return _y @view @external def get_z() -> uint256: result: uint256 = A.z return result
From the above code examples in contract B.vy
, we can see that we use A.vy
's state by initializing using the initializes: A
magic. Also, i can access all @internal
functions of the initialized contract. For example, I can call A._add(_x, _y)
. However, it's not possible to call external functions at this moment. A.add(_x, _y)
will throw. To archive this, we need to use exports: A.add
just like it's done in C.vy
.
With exports, the external function is now available in the initializing contract. We are going to witness this later when it comes to interacting with the code.
scripts/deploy_B.py
from ape import project, accounts def main(): account = accounts.load('meta_wallet') # Replace with your actual account alias _x = 3 _y = 4 # Deploy the contract contract = account.deploy(project.B, _x, _y) # Initial values for x and y # Display initial values print(f"Initial x: {contract.get_x()} \u2705") print(f"Initial y: {contract.get_y()} \u2705") # Call the add method contract.set_value(5, 15, sender=account) # Fetch and display the result result = contract.get_z() print(f"Result (z): {result} \u2705")
From the image above, we see that we get exactly what we expect from the way how initializes
and exports
operate.✅
scripts/deploy_C.py
from ape import project, accounts def main(): account = accounts.load('meta_wallet') # Replace with your actual account name _x = 5 _y = 10 # Deploy the contract contract = account.deploy(project.C, _x, _y) # Initial values for x and y # Display initial values print(f"Initial x: {contract.get_x()} \u2705") print(f"Initial y: {contract.get_y()} \u2705") # Call the add method contract.add(5, 15, sender=account) # Fetch and display the result result = contract.get_z() print(f"Result (z): {result} \u2705")
Here also, you see that we can access the contract state of A
just buy initializing and exporting it's external
functions.✅ Therefore, one can just call from C
, contract.add()
.
Thanks for reading. Let me hope my efforts help you at some stage. If you find the post helpful, please don't forget to give a like, and comment below if you need any help.
Top comments (0)