Attribute Macro soroban_sdk::contracttype
source · #[contracttype]
Expand description
Generates conversions from the struct/enum from/into a Val
.
There are some constraints on the types that are supported:
- Enums with integer values must have an explicit integer literal for every variant.
- Enums with unit variants are supported.
- Enums with tuple-like variants with a maximum of one tuple field are
supported. The tuple field must be of a type that is also convertible to and
from
Val
. - Enums with struct-like variants are not supported.
- Structs are supported. All fields must be of a type that is also
convertible to and from
Val
. - All variant names, field names, and type names must be 10-characters or less in length.
Includes the type in the contract spec so that clients can generate bindings for the type.
Examples
Defining a contract type that is a struct and use it in a contract.
#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Env, Symbol};
#[contracttype]
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct State {
pub count: u32,
pub last_incr: u32,
}
#[contract]
pub struct Contract;
#[contractimpl]
impl Contract {
/// Increment increments an internal counter, and returns the value.
pub fn increment(env: Env, incr: u32) -> u32 {
// Get the current count.
let mut state = Self::get_state(env.clone());
// Increment the count.
state.count += incr;
state.last_incr = incr;
// Save the count.
env.storage().persistent().set(&symbol_short!("STATE"), &state);
// Return the count to the caller.
state.count
}
/// Return the current state.
pub fn get_state(env: Env) -> State {
env.storage().persistent()
.get(&symbol_short!("STATE"))
.unwrap_or_else(|| State::default()) // If no value set, assume 0.
}
}
#[test]
fn test() {
let env = Env::default();
let contract_id = env.register_contract(None, Contract);
let client = ContractClient::new(&env, &contract_id);
assert_eq!(client.increment(&1), 1);
assert_eq!(client.increment(&10), 11);
assert_eq!(
client.get_state(),
State {
count: 11,
last_incr: 10,
},
);
}
Defining contract types that are three different types of enums and using them in a contract.
#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Symbol, Env};
/// A tuple enum is stored as a two-element vector containing the name of
/// the enum variant as a Symbol, then the value in the tuple.
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Color {
Red(Intensity),
Blue(Shade),
}
/// A unit enum is stored as a single-element vector containing the name of
/// the enum variant as a Symbol.
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Shade {
Light,
Dark,
}
/// An integer enum is stored as its integer value.
#[contracttype]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
pub enum Intensity {
Low = 1,
High = 2,
}
#[contract]
pub struct Contract;
#[contractimpl]
impl Contract {
/// Set the color.
pub fn set(env: Env, c: Color) {
env.storage().persistent().set(&symbol_short!("COLOR"), &c);
}
/// Get the color.
pub fn get(env: Env) -> Option<Color> {
env.storage().persistent()
.get(&symbol_short!("COLOR"))
}
}
#[test]
fn test() {
let env = Env::default();
let contract_id = env.register_contract(None, Contract);
let client = ContractClient::new(&env, &contract_id);
assert_eq!(client.get(), None);
client.set(&Color::Red(Intensity::High));
assert_eq!(client.get(), Some(Color::Red(Intensity::High)));
client.set(&Color::Blue(Shade::Light));
assert_eq!(client.get(), Some(Color::Blue(Shade::Light)));
}