Smart contract anatomy
A smart contract runs a piece of code and maintains the state of the interactions with that code by different accounts. The three components of a smart contract are the Data, Functions, and Events + Logs
Data
Smart contract data can be stored either permanently or temporarily. The placement of variables is decided by the programmer. Permanent variables are placed into storage, while temporary variables are placed into memory.
Storage
Permanent storage is much more expensive than temporary memory. See more information about the ICON execution environments to understand exactly how data gets permanently stored, including information on the data structures and repercussions associated with them.
A permanent variable is defined as a member of a class.
public class HelloWorld {
private String name; // Permanent variable
}
Memory
Temporary memory is, conversely, much cheaper than permanent storage.
Temporary variables are defined as variables inside of functions.
public class HelloWorld {
private String name;
public HelloWorld(String name) {
this.name = name;
}
@External(readonly=true)
public String getGreeting() {
String msg = "Hello " + name + "!"; // `msg` is a temporary variable
Context.println(msg);
return msg;
}
}
Functions
Functions on ICON are equivalent to functions in Java. ICON adds additional annotations that are parsed by the Java execution environment to do things like make a function available as a part of the public API. These annotations can be found here (opens in a new tab).
Java classes (opens in a new tab)
Java methods (opens in a new tab)
Writing functions
Here is an example of a function that is made available for the public API of a smart contract:
@External(readonly=true)
public String getGreeting() {
String msg = "Hello " + name + "!";
Context.println(msg);
return msg;
}
Events and logs
Events are useful to track that some action has occurred within the processing of a smart contract. They are written to the blockchain as logs, which can then be used by external interfaces. For example, they can be used in user interfaces to provide updates on the status of an operation:
// From https://github.com/icon-project/java-score-examples/blob/master/sample-crowdsale/src/main/java/com/iconloop/score/example/SampleCrowdsale.java
public class SampleCrowdsale
{
...
@External
public void tokenFallback(Address _from, BigInteger _value, byte[] _data) {
// check if the caller is a token SCORE address that this SCORE is interested in
Context.require(Context.getCaller().equals(this.tokenScore));
// depositing tokens can only be done by owner
Context.require(Context.getOwner().equals(_from));
// value should be greater than zero
Context.require(_value.compareTo(BigInteger.ZERO) >= 0);
// start Crowdsale hereafter
Context.require(this.crowdsaleClosed);
this.crowdsaleClosed = false;
// emit eventlog
CrowdsaleStarted(this.fundingGoal, this.deadline);
}
...
@EventLog
protected void CrowdsaleStarted(BigInteger fundingGoal, long deadline) {}
...
}