Functions

Constant size values stored on the stack or in memory can be passed into and returned by functions.

Syntax
Function :
   FunctionQualifiers fn IDENTIFIER
      ( FunctionParameters? )
      FunctionReturnType?
      {
      FunctionStatements*
      }

FunctionQualifiers :
   pub?

FunctionStatements :
         ReturnStatement
      | VariableDeclarationStatement
      | AssignStatement
      | AugmentedAssignStatement
      | ForStatement
      | WhileStatement
      | IfStatement
      | AssertStatement
      | BreakStatement
      | ContinueStatement
      | RevertStatement
      | Expression

FunctionParameters :
   self? | self,? FunctionParam (, FunctionParam)* ,?

FunctionParam :
   FunctionParamLabel? IDENTIFIER : Types

FunctionParamLabel :
   _ | IDENTIFIER

FunctionReturnType :
   -> Types

A function definition consists of name and code block along with an optional list of parameters and return value. Functions are declared with the keyword fn. Functions may declare a set of input parameters, through which the caller passes arguments into the function, and the output type of the value the function will return to its caller on completion.

When referred to, a function yields a first-class value of the corresponding zero-sized function type, which when called evaluates to a direct call to the function.

A function header prepends a set or curly brackets {...} which contain the function body.

For example, this is a simple function:

fn add(x: u256, y: u256) -> u256 {
    return x + y
}

Functions can be defined inside of a contract, inside of a struct, or at the "top level" of a module (that is, not nested within another item).

Example:

fn add(_ x: u256, _ y: u256) -> u256 {
    return x + y
}

contract CoolCoin {
    balance: Map<address, u256>

    fn transfer(mut self, from sender: address, to recipient: address, value: u256) -> bool {
        if self.balance[sender] < value {
            return false
        }
        self.balance[sender] -= value
        self.balance[recipient] += value
        return true
    }
    pub fn demo(mut self) {
        let ann: address = 0xaa
        let bob: address = 0xbb
        self.balance[ann] = 100

        let bonus: u256 = 2
        let value: u256 = add(10, bonus)
        let ok: bool = self.transfer(from: ann, to: bob, value)
    }
}

Function parameters have optional labels. When a function is called, the arguments must be labeled and provided in the order specified in the function definition.

The label of a parameter defaults to the parameter name; a different label can be specified by adding an explicit label prior to the parameter name. For example:

fn encrypt(msg cleartext: u256, key: u256) -> u256 {
    return cleartext ^ key
}

fn demo() {
    let out: u256 = encrypt(msg: 0xdecafbad, key: 0xfefefefe)
}

Here, the first parameter of the encrypt function has the label msg, which is used when calling the function, while the parameter name is cleartext, which is used inside the function body. The parameter name is an implementation detail of the function, and can be changed without modifying any function calls, as long as the label remains the same.

When calling a function, a label can be omitted when the argument is a variable with a name that matches the parameter label. Example:

let msg: u256 = 0xdecafbad
let cyf: u256 = encrypt(msg, key: 0x1234)

A parameter can also be specified to have no label, by using _ in place of a label in the function definition. In this case, when calling the function, the corresponding argument must not be labeled. Example:

fn add(_ x: u256, _ y: u256) -> u256 {
    return x + y
}
fn demo() {
    let sum: u256 = add(16, 32)
}

Functions defined inside of a contract or struct may take self as a parameter. This gives the function the ability to read and write contract storage or struct fields, respectively. If a function takes self as a parameter, the function must be called via self. For example:

let ok: bool = self.transfer(from, to, value)

self is expected to come first parameter in the function's parameter list.

Functions can also take a Context object which gives access to EVM features that read or write blockchain and transaction data. Context is expected to be first in the function's parameter list unless the function takes self, in which case Context should come second.