Calling Other Functions
A contract is a collection of persistent state variables and functions which may manipulate these variables.
Functions and state variables within a contract's scope are said to belong to that contract. A contract can only access and modify its own state.
If a contract wishes to access or modify another contract's state, it must make a call to an external function of the other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called.
Defining a contract
A contract may be declared and given a name using the contract
keyword (see snippet below). By convention, contracts are named in PascalCase
.
contract MyContract {
// Imports
// Storage
// Functions
}
There is no main()
(GitHub link) function within a Noir contract
scope. More than one function can be an entrypoint.
Add as a dependency in Nargo.toml
Import the contract that you want to call into your Nargo.toml
under dependencies
like this:
token = { git="https://github.com/AztecProtocol/aztec-packages/", tag="aztec-packages-v0.66.0", directory="noir-projects/noir-contracts/contracts/token_contract" }
Import into your contract
At the top of your contract, import the contract you want to call like this:
use token::Token;
Call the function
To call the function, you need to
- Specify the address of the contract with
Contract::at(contract_address)
- Call the function name with
.function_name()
- Pass the parameters into the function call, like
.function_name(param1,param2)
- Specify the type of call you want to make and pass a mut reference to the context, like
.call(&mut context)
Private calls
To call a private function, you can just use call()
like this:
Token::at(token).transfer(recipient, amount).call(&mut context);
Source code: noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr#L46-L48
Public -> Public calls
To call a public function from a public function, it is the same as above. You can just use call()
like this:
let _ = Token::at(collateral_asset)
.transfer_in_public(context.msg_sender(), context.this_address(), amount, nonce)
.call(&mut context);
Source code: noir-projects/noir-contracts/contracts/lending_contract/src/main.nr#L131-L135
Private -> Public calls
To call a public function from private, you will need to enqueue it like this:
Lending::at(context.this_address())
._deposit(AztecAddress::from_field(on_behalf_of), amount, collateral_asset)
.enqueue(&mut context);
Source code: noir-projects/noir-contracts/contracts/lending_contract/src/main.nr#L117-L121
Public functions are always executed after private execution. To learn why, read the concepts overview.
Other call types
There are other call types, for example to ensure no state changes are made. You can learn more about them in the call types glossary.