Starcoin Stdib's Config Module
Starcoin Stdib's Config Module
* By Starcoin community

Starcoin’s Stdlib

Starcoin has a very important feature: Stdlib.

Unlike Ethereum, account model in Starcoin, the data generated by the contract is stored dispersedly in each user’s own account, and there are no common security issues such as large arrays. So Starcoin can easily implement the official standard library Stdlib, define contracts with some basic functions, and make it convenient for other contracts to call. Starcoin’s Stdlib is implemented using Move, which not only includes some chain-related core logic, such as enhanced PoW consensus, economic models, etc., but also includes some basic protocols, such as Token protocol, on-chain governance DAO, NFT protocol, Oracle protocol, contract upgrade protocol, Config protocol, etc. For the introduction and use of these protocols, you can view a more detailed introduction here.

image-20220201154949416

Config Module in Stdlib

Config is a general module in Stdlib, used to store and manipulate some common configurations. In Starcoin’s Stdlib, there are many features that use the Config module to store some global configurations:

  • VMConfig
  • ConsensusConfig
  • RewardConfig
  • OnchainConfig

Advantages to doing this:

  • Avoid hard coding
  • Unified management
  • If necessary, you can update these configurations at any time to avoid hard forks
starcoin_configs

Source Code of Config

Functions of the Config module are similar to the Map with generics, and the stored Value can be obtained through the Key. Although there are many functions in Stdlib, the code of the contract is very concise:

  • Config is used to store the payload
  • ModifyConfigCapability saves the account_address which modified the Config permission, after modification, a ConfigChangeEvent will be generated
  /// A generic singleton resource that holds a value of a specific type.
    struct Config<ConfigValue: copy + drop + store> has key { payload: ConfigValue }

    /// Accounts with this privilege can modify config of type ConfigValue under account_address
    struct ModifyConfigCapability<ConfigValue: copy + drop + store> has store {
        account_address: address,
        events: Event::EventHandle<ConfigChangeEvent<ConfigValue>>,
    }

    /// A holder for ModifyConfigCapability, for extract and restore ModifyConfigCapability.
    struct ModifyConfigCapabilityHolder<ConfigValue: copy + drop + store> has key, store {
        cap: Option<ModifyConfigCapability<ConfigValue>>,
    }

Operator Functions in Config Module:

	/// Get a copy of `ConfigValue` value stored under `addr`.
    public fun get_by_address<ConfigValue: copy + drop + store>(addr: address): ConfigValue acquires Config

    /// Check whether the config of `ConfigValue` type exists under `addr`.
    public fun config_exist_by_address<ConfigValue: copy + drop + store>(addr: address): bool 
    
    /// Set a config item to a new value with capability stored under signer
    public fun set<ConfigValue: copy + drop + store>(account: &signer, payload: ConfigValue) acquires Config,ModifyConfigCapabilityHolder
    
    /// Publish a new config item under account address.
    public fun publish_new_config<ConfigValue: copy + drop + store>(account: &signer, payload: ConfigValue)
  • “get_by_address” function: Acquire ConfigValue from addr
  • “config_exsit_by_address” function: Determine whether there is ConfigValue in addr
  • “set” function: Set Config to a new payload value, which can be modified only with ModifyConfigCapability permission
  • “publish_new_config”: Generate a new config

Usage of Config

Since the Config module had lots of convenience, the global configuration of Stdlib is managed by the Config contract, and it is combined with the governance function on the chain to ensure the security of the global configuration in Stdlib. Here we use RewardConfig to understand the use of the Config module:

/// Reward configuration
    struct RewardConfig has copy, drop, store {
        /// how many blocks delay reward distribution.
        reward_delay: u64,
    }

    /// Module initialization.
    public fun initialize(account: &signer, reward_delay: u64)
    
    /// Create a new reward config mainly used in DAO.
    public fun new_reward_config(reward_delay: u64) : RewardConfig
    
    /// Get reward configuration.
    public fun get_reward_config(): RewardConfig

RewardConfig is stored under GENESIS_ADDRESS (Genesis Account is the genesis account of Starcoin, has no private key, and is not managed by anyone), and is used to save the configuration related to block rewards. Only one variable “reward_delay” in RewardConfig, which means the number of blocks for delayed payment of rewards:

  • “initialize” function: Initialization function, call Config::publish_new_config to set RewardConfig
  • “new_reward_config” function: Generate a RewardConfig instance according to the specified reward_delay (new_reward_config function and Config::set function can update RewardConfig)
  • “get_reward_config” function: call Config::get_by_address function to get the latest RewardConfig

Summarize

Config is a global module, any account can be used to store and manage the configuration in its own address. In order to avoid the problem of large arrays, Config does not use arrays to implement it, which is safe and reliable. Some global configurations of Starcoin are saved under the Genesis Account account using the Config contract. Those interested can view the complete code.