TokenContract
o1js / Modules / TokenContract
Class: TokenContract
Base token contract which
- implements the
Approvable
API, with theapproveBase()
method left to be defined by subclasses - implements the
Transferable
API as a wrapper around theApprovable
API
Hierarchy
↳
TokenContract
Table of contents
Constructors
Properties
- #_senderState
- #executionState
- address
- events
- tokenId
- _maxProofsVerified
- _methodMetadata
- _methods
- _provers
- _verificationKey
Accessors
Methods
- approve
- approveAccountUpdate
- approveAccountUpdates
- approveBase
- checkZeroBalanceChange
- deploy
- deriveTokenId
- emitEvent
- fetchEvents
- forEachUpdate
- init
- newSelf
- requireSignature
- send
- setPermissions
- setValue
- sign
- skipAuthorization
- transfer
- Proof
- analyzeMethods
- compile
- digest
- runOutsideCircuit
Constructors
constructor
• new TokenContract(address
, tokenId?
)
Parameters
Name | Type |
---|---|
address | PublicKey |
tokenId? | Field |
Inherited from
Defined in
Properties
#_senderState
• Private
#_senderState: Object
Type declaration
Name | Type |
---|---|
sender | PublicKey |
transactionId | number |
Inherited from
Defined in
#executionState
• Private
#executionState: undefined
| ExecutionState
Inherited from
Defined in
address
• address: PublicKey
Inherited from
Defined in
events
• events: Object
= {}
A list of event types that can be emitted using this.emitEvent()`.
Index signature
▪ [key: string
]: FlexibleProvablePure
\<any
>
Inherited from
Defined in
tokenId
• tokenId: Field
Inherited from
Defined in
_maxProofsVerified
▪ Static
Optional
_maxProofsVerified: 0
| 2
| 1
Inherited from
SmartContract._maxProofsVerified
Defined in
_methodMetadata
▪ Static
Optional
_methodMetadata: Record
\<string
, { actions
: number
; digest
: string
; gates
: Gate
[] ; hasReturn
: boolean
; rows
: number
}>
Inherited from
Defined in
_methods
▪ Static
Optional
_methods: MethodInterface
[]
Inherited from
Defined in
_provers
▪ Static
Optional
_provers: Prover
[]
Inherited from
Defined in
_verificationKey
▪ Static
Optional
_verificationKey: Object
Type declaration
Name | Type |
---|---|
data | string |
hash | Field |
Inherited from
SmartContract._verificationKey
Defined in
Accessors
account
• get
account(): Account
Current account of the SmartContract.
Returns
Account
Inherited from
SmartContract.account
Defined in
balance
• get
balance(): Object
Balance of this SmartContract.
Returns
Object
Name | Type |
---|---|
addInPlace | (x : string | number | bigint | UInt64 | UInt32 | Int64 ) => void |
subInPlace | (x : string | number | bigint | UInt64 | UInt32 | Int64 ) => void |
Inherited from
SmartContract.balance
Defined in
currentSlot
• get
currentSlot(): CurrentSlot
Current global slot on the network. This is the slot at which this transaction is included in a block. Since we cannot know this value
at the time of transaction construction, this only has the assertBetween()
method but no get()
(impossible to implement)
or assertEquals()
(confusing, because the developer can't know the exact slot at which this will be included either)
Returns
CurrentSlot
Inherited from
SmartContract.currentSlot
Defined in
internal
• get
internal(): Object
Helper methods to use from within a token contract.
Returns
Object
Name | Type |
---|---|
burn | (__namedParameters : { address : PublicKey | AccountUpdate | SmartContract ; amount : number | bigint | UInt64 }) => AccountUpdate |
mint | (__namedParameters : { address : PublicKey | AccountUpdate | SmartContract ; amount : number | bigint | UInt64 }) => AccountUpdate |
send | (__namedParameters : { amount : number | bigint | UInt64 ; from : PublicKey | AccountUpdate | SmartContract ; to : PublicKey | AccountUpdate | SmartContract }) => AccountUpdate |
Defined in
lib/mina/token/token-contract.ts:76
network
• get
network(): Network
Current network state of the SmartContract.
Returns
Network
Inherited from
SmartContract.network
Defined in
self
• get
self(): AccountUpdate
Returns the current AccountUpdate associated to this SmartContract.
Returns
Inherited from
SmartContract.self
Defined in
sender
• get
sender(): PublicKey
The public key of the current transaction's sender account.
Throws an error if not inside a transaction, or the sender wasn't passed in.
Warning: The fact that this public key equals the current sender is not part of the proof. A malicious prover could use any other public key without affecting the validity of the proof.
Returns
Inherited from
SmartContract.sender
Defined in
token
• get
token(): Object
Returns
Object
Name | Type |
---|---|
id | Field |
parentTokenId | Field |
tokenOwner | PublicKey |
burn | (__namedParameters : { address : PublicKey | AccountUpdate | SmartContract ; amount : number | bigint | UInt64 }) => AccountUpdate |
mint | (__namedParameters : { address : PublicKey | AccountUpdate | SmartContract ; amount : number | bigint | UInt64 }) => AccountUpdate |
send | (__namedParameters : { amount : number | bigint | UInt64 ; from : PublicKey | AccountUpdate | SmartContract ; to : PublicKey | AccountUpdate | SmartContract }) => AccountUpdate |
Deprecated
SmartContract.token
will be removed, and token methods will only be available on TokenContract.internal
.
Instead of SmartContract.token.id
, use TokenContract.deriveTokenId()
.
For security reasons, it is recommended to use TokenContract as the base contract for all tokens.
Inherited from
SmartContract.token
Defined in
tokenSymbol
• get
tokenSymbol(): Object
Returns
Object
Name | Type |
---|---|
set | (tokenSymbol : string ) => void |
Deprecated
use this.account.tokenSymbol
Inherited from
SmartContract.tokenSymbol
Defined in
Methods
approve
▸ approve(update
): void
Approve an account update or tree / forest of updates. Doing this means you include the account update in the zkApp's public input, which allows you to read and use its content in a proof, make assertions about it, and modify it.
`@method` myApprovingMethod(update: AccountUpdate) {
this.approve(update);
// read balance on the account (for example)
let balance = update.account.balance.getAndRequireEquals();
}
Under the hood, "approving" just means that the account update is made a child of the zkApp in the tree of account updates that forms the transaction. Similarly, if you pass in an AccountUpdateTree, the entire tree will become a subtree of the zkApp's account update.
Passing in a forest is a bit different, because it means you set the entire children of the zkApp's account update
at once. approve()
will fail if the zkApp's account update already has children, to prevent you from accidentally
excluding important information from the public input.
Parameters
Name | Type |
---|---|
update | AccountUpdate | AccountUpdateTree | AccountUpdateForest |
Returns
void
Inherited from
Defined in
approveAccountUpdate
▸ approveAccountUpdate(accountUpdate
): void
Approve a single account update (with arbitrarily many children).
Parameters
Name | Type |
---|---|
accountUpdate | AccountUpdate | AccountUpdateTree |
Returns
void
Defined in
lib/mina/token/token-contract.ts:137
approveAccountUpdates
▸ approveAccountUpdates(accountUpdates
): void
Approve a list of account updates (with arbitrarily many children).
Parameters
Name | Type |
---|---|
accountUpdates | (AccountUpdate | AccountUpdateTree )[] |
Returns
void
Defined in
lib/mina/token/token-contract.ts:145
approveBase
▸ Abstract
approveBase(forest
): void
Parameters
Name | Type |
---|---|
forest | AccountUpdateForest |
Returns
void
Defined in
lib/mina/token/token-contract.ts:83
checkZeroBalanceChange
▸ checkZeroBalanceChange(updates
): void
Use forEachUpdate()
to prove that the total balance change of child account updates is zero.
This is provided out of the box as it is both a good example, and probably the most common implementation, of approveBase()
.
Parameters
Name | Type |
---|---|
updates | AccountUpdateForest |
Returns
void
Defined in
lib/mina/token/token-contract.ts:121
deploy
▸ deploy(args?
): void
Deploys a TokenContract.
In addition to base smart contract deployment, this adds two steps:
- set the
access
permission toproofOrSignature()
, to prevent against unauthorized token operations- not doing this would imply that anyone can bypass token contract authorization and simply mint themselves tokens
- require the zkapp account to be new, using the
isNew
precondition. this guarantees that the access permission is set from the very start of the existence of this account. creating the zkapp account before deployment would otherwise be a security vulnerability that is too easy to introduce.
Note that because of the isNew
precondition, the zkapp account must not be created prior to calling deploy()
.
If the contract needs to be re-deployed, you can switch off this behaviour by overriding the isNew
precondition:
deploy() {
super.deploy();
// DON'T DO THIS ON THE INITIAL DEPLOYMENT!
this.account.isNew.requireNothing();
}
Parameters
Name | Type |
---|---|
args? | DeployArgs |
Returns
void
Overrides
Defined in
lib/mina/token/token-contract.ts:51
deriveTokenId
▸ deriveTokenId(): Field
Returns the tokenId
of the token managed by this contract.
Returns
Defined in
lib/mina/token/token-contract.ts:69
emitEvent
▸ emitEvent\<K
>(type
, event
): void
Emits an event. Events will be emitted as a part of the transaction and can be collected by archive nodes.
Type parameters
Name | Type |
---|---|
K | extends string | number |
Parameters
Name | Type |
---|---|
type | K |
event | any |
Returns
void
Inherited from
Defined in
fetchEvents
▸ fetchEvents(start?
, end?
): Promise
\<{ blockHash
: string
; blockHeight
: UInt32
; chainStatus
: string
; event
: { data
: ProvablePure
\<any
> ; transactionInfo
: { transactionHash
: string
; transactionMemo
: string
; transactionStatus
: string
} } ; globalSlot
: UInt32
; parentBlockHash
: string
; type
: string
}[]>
Asynchronously fetches events emitted by this SmartContract and returns an array of events with their corresponding types.
Parameters
Name | Type | Description |
---|---|---|
start? | UInt32 | The start height of the events to fetch. |
end? | UInt32 | The end height of the events to fetch. If not provided, fetches events up to the latest height. |
Returns
Promise
\<{ blockHash
: string
; blockHeight
: UInt32
; chainStatus
: string
; event
: { data
: ProvablePure
\<any
> ; transactionInfo
: { transactionHash
: string
; transactionMemo
: string
; transactionStatus
: string
} } ; globalSlot
: UInt32
; parentBlockHash
: string
; type
: string
}[]>
A promise that resolves to an array of objects, each containing the event type and event data for the specified range.
Async
Throws
If there is an error fetching events from the Mina network.
Example
const startHeight = UInt32.from(1000);
const endHeight = UInt32.from(2000);
const events = await myZkapp.fetchEvents(startHeight, endHeight);
console.log(events);
Inherited from
Defined in
forEachUpdate
▸ forEachUpdate(updates
, callback
): void
Iterate through the account updates in updates
and apply callback
to each.
This method is provable and is suitable as a base for implementing approveUpdates()
.
Parameters
Name | Type |
---|---|
updates | AccountUpdateForest |
callback | (update : AccountUpdate , usesToken : Bool ) => void |
Returns
void
Defined in
lib/mina/token/token-contract.ts:90
init
▸ init(): void
SmartContract.init()
will be called only when a SmartContract will be first deployed, not for redeployment.
This method can be overridden as follows
class MyContract extends SmartContract {
init() {
super.init();
this.account.permissions.set(...);
this.x.set(Field(1));
}
}
Returns
void
Inherited from
Defined in
newSelf
▸ newSelf(methodName?
): AccountUpdate
Same as SmartContract.self
but explicitly creates a new AccountUpdate.
Parameters
Name | Type |
---|---|
methodName? | string |
Returns
Inherited from
Defined in
requireSignature
▸ requireSignature(): void
Use this command if the account update created by this SmartContract should be signed by the account owner, instead of authorized with a proof.
Note that the smart contract's Permissions determine which updates have to be (can be) authorized by a signature.
If you only want to avoid creating proofs for quicker testing, we advise you to
use LocalBlockchain({ proofsEnabled: false })
instead of requireSignature()
. Setting
proofsEnabled
to false
allows you to test your transactions with the same authorization flow as in production,
with the only difference being that quick mock proofs are filled in instead of real proofs.
Returns
void
Inherited from
SmartContract.requireSignature
Defined in
send
▸ send(args
): AccountUpdate
Parameters
Name | Type |
---|---|
args | Object |
args.amount | number | bigint | UInt64 |
args.to | PublicKey | AccountUpdate | SmartContract |
Returns
Inherited from
Defined in
setPermissions
▸ setPermissions(permissions
): void
Parameters
Name | Type |
---|---|
permissions | Permissions |
Returns
void
Deprecated
use this.account.permissions.set()
Inherited from
Defined in
setValue
▸ setValue\<T
>(maybeValue
, value
): void
Type parameters
Name |
---|
T |
Parameters
Name | Type |
---|---|
maybeValue | SetOrKeep \<T > |
value | T |
Returns
void
Deprecated
use this.account.<field>.set()
Inherited from
Defined in
sign
▸ sign(zkappKey?
): void
Parameters
Name | Type |
---|---|
zkappKey? | PrivateKey |
Returns
void
Deprecated
this.sign()
is deprecated in favor of this.requireSignature()
Inherited from
Defined in
skipAuthorization
▸ skipAuthorization(): void
Use this command if the account update created by this SmartContract should have no authorization on it, instead of being authorized with a proof.
WARNING: This is a method that should rarely be useful. If you want to disable proofs for quicker testing, take a look
at LocalBlockchain({ proofsEnabled: false })
, which causes mock proofs to be created and doesn't require changing the
authorization flow.
Returns
void
Inherited from
SmartContract.skipAuthorization
Defined in
transfer
▸ transfer(from
, to
, amount
): void
Transfer amount
of tokens from from
to to
.
Parameters
Name | Type |
---|---|
from | PublicKey | AccountUpdate |
to | PublicKey | AccountUpdate |
amount | number | bigint | UInt64 |
Returns
void
Defined in
lib/mina/token/token-contract.ts:155
Proof
▸ Static
Proof(): typeof __class
Returns a Proof type that belongs to this SmartContract.
Returns
typeof __class
Inherited from
Defined in
analyzeMethods
▸ Static
analyzeMethods(«destructured»?
): Record
\<string
, { actions
: number
; digest
: string
; gates
: Gate
[] ; hasReturn
: boolean
; rows
: number
}>
This function is run internally before compiling a smart contract, to collect metadata about what each of your smart contract methods does.
For external usage, this function can be handy because calling it involves running all methods in the same "mode" as compile()
does,
so it serves as a quick-to-run check for whether your contract can be compiled without errors, which can greatly speed up iterating.
analyzeMethods()
will also return the number of rows
of each of your method circuits (i.e., the number of constraints in the underlying proof system),
which is a good indicator for circuit size and the time it will take to create proofs.
To inspect the created circuit in detail, you can look at the returned gates
.
Note: If this function was already called before, it will short-circuit and just return the metadata collected the first time.
Parameters
Name | Type |
---|---|
«destructured» | Object |
› printSummary | undefined | boolean |
Returns
Record
\<string
, { actions
: number
; digest
: string
; gates
: Gate
[] ; hasReturn
: boolean
; rows
: number
}>
an object, keyed by method name, each entry containing:
rows
the size of the constraint system created by this methoddigest
a digest of the method circuithasReturn
a boolean indicating whether the method returns a valueactions
the number of actions the method dispatchesgates
the constraint system, represented as an array of gates
Inherited from
Defined in
compile
▸ Static
compile(«destructured»?
): Promise
\<{ provers
: Prover
[] ; verificationKey
: { data
: string
; hash
: Field
} ; verify
: (statement
: Statement
\<FieldConst
>, proof
: unknown
) => Promise
\<boolean
> }>
Compile your smart contract.
This generates both the prover functions, needed to create proofs for running @method
s,
and the verification key, needed to deploy your zkApp.
Although provers and verification key are returned by this method, they are also cached internally and used when needed, so you don't actually have to use the return value of this function.
Under the hood, "compiling" means calling into the lower-level Pickles and Kimchi libraries to create multiple prover & verifier indices (one for each smart contract method as part of a "step circuit" and one for the "wrap circuit" which recursively wraps it so that proofs end up in the original finite field). These are fairly expensive operations, so expect compiling to take at least 20 seconds, up to several minutes if your circuit is large or your hardware is not optimal for these operations.
Parameters
Name | Type |
---|---|
«destructured» | Object |
› cache | undefined | Cache |
› forceRecompile | undefined | boolean |
Returns
Promise
\<{ provers
: Prover
[] ; verificationKey
: { data
: string
; hash
: Field
} ; verify
: (statement
: Statement
\<FieldConst
>, proof
: unknown
) => Promise
\<boolean
> }>
Inherited from
Defined in
digest
▸ Static
digest(): string
Computes a hash of your smart contract, which will reliably change whenever one of your method circuits changes. This digest is quick to compute. it is designed to help with deciding whether a contract should be re-compiled or a cached verification key can be used.
Returns
string
the digest, as a hex string
Inherited from
Defined in
runOutsideCircuit
▸ Static
runOutsideCircuit(run
): void
Parameters
Name | Type |
---|---|
run | () => void |
Returns
void
Inherited from
SmartContract.runOutsideCircuit