Valocracy

Valocracy is a novel social, economic, and political framework that leverages blockchain technology to create new forms of organizations with the goal of empowering communities along with their individuals and their combined efforts. It aims to provide a structured approach to building more efficient and fair decentralized organizations.

Core Principles

  1. Tokenized Effort: Effort is tokenized through two distinct tokens:

    • Governance Power: Implemented as ERC20Votes with Soulbound Degradable Governance (SDG) standard, ensuring voting power cannot be transferred and decays over time without active participation
    • Economic Power: Implemented as ERC20 with ERC4626 vault interface, representing shares of the underlying treasury asset
  2. Valueholder Concept: Blurs the distinction between shareholders and laborers, allowing individuals to decide when to act as paid laborers or shareholders.

  3. Time-Based Governance: Governance power follows a dynamic curve:

    • Stable Period: Initial period where governance power remains constant
    • Decay Period: Following the stable period, governance power gradually decreases over time
    • This mechanism ensures active participation while preventing governance attacks

Smart Contracts

The project consists of several core smart contracts:

  • Valocracy.sol: The main contract implementing ERC20Votes with SDG.
  • Treasury.sol: Manages the collective treasury and economic power distribution using ERC20
  • SDG.sol: Implements the IERC7787 for Soulbound Degradable Governance
  • Interfaces/: Contains the core interfaces for the system

Documentation and Coverage

Learn More

For a deeper understanding of Valocracy's principles and vision, please read our Manifesto.

Contributing

Please see our CONTRIBUTING.md for details on how to contribute to this project.

Contents

IERC7787

Git Source

Functions

stablePeriod

Returns the grace period duration before the voting units begins decaying. This period is fixed to 90 days. But it can be overridden in derived contracts.

function stablePeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The duration of the grace period in seconds.

decayPeriod

Returns the duration of the decay period during which the voting units decreases. This period is fixed to 90 days. But it can be overridden in derived contracts.

function decayPeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The duration of the decay period in seconds.

accountStats

Returns the raw last participation timestamp of an account without any decay adjustments.

function accountStats(address account) external view returns (uint32);

Errors

TokenSoulbound

Error thrown when attempting to transfer a soulbound token

error TokenSoulbound();

ITreasury

Git Source

Functions

asset

Returns the address of the single underlying asset token used by the treasury for accounting, depositing, and withdrawing.

function asset() external view returns (address);

Returns

NameTypeDescription
<none>addressThe address of the underlying asset token

totalAssets

Returns the total amount of the single underlying asset that is managed by the treasury.

function totalAssets() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total amount of the underlying asset

previewWithdraw

Calculates the amount of the underlying asset that would be returned from burning the given amount of shares.

function previewWithdraw(uint256 shares) external view returns (uint256);

Parameters

NameTypeDescription
sharesuint256The amount of shares to calculate assets for

Returns

NameTypeDescription
<none>uint256The amount of underlying asset that would be returned

deposit

Deposits the underlying asset into the treasury and mints shares to the receiver. Only callable by the Valocracy contract.

function deposit(address receiver, uint256 shares) external;

Parameters

NameTypeDescription
receiveraddressThe address that will receive the shares
sharesuint256The amount of shares to mint

withdraw

Withdraws the underlying asset from the treasury by burning shares. Transfers the corresponding amount of the underlying asset to the receiver.

function withdraw(address receiver, uint256 shares) external;

Parameters

NameTypeDescription
receiveraddressThe address that will receive the underlying asset
sharesuint256The amount of shares to burn

Events

Deposit

Emitted when a new deposit of the underlying asset is made.

event Deposit(address indexed receiver, uint256 shares);

Parameters

NameTypeDescription
receiveraddressThe address that received the shares
sharesuint256The amount of shares minted

Withdraw

Emitted when a withdrawal of the underlying asset is made.

event Withdraw(address indexed owner, address indexed receiver, uint256 assets, uint256 shares);

Parameters

NameTypeDescription
owneraddressThe address that burned the shares
receiveraddressThe address that received the underlying asset
assetsuint256The amount of underlying asset withdrawn
sharesuint256The amount of shares burned

Errors

NotAuthorized

Emitted when a non-authorized account attempts to call a function.

error NotAuthorized(address caller);

IValocracy

Git Source

Functions

balanceOf

*Returns the balance of an account with decay applied. Implements the EIP-7787 decay mechanism:

  • Full balance during stable period
  • Linear decay during decay period
  • Zero balance after decay period ends*
function balanceOf(address account) external view returns (uint256);

Parameters

NameTypeDescription
accountaddressThe address to check the balance for

Returns

NameTypeDescription
<none>uint256The current balance with decay applied

stablePeriod

Returns the stable period duration in seconds.

function stablePeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The stable period duration

decayPeriod

Returns the decay period duration in seconds.

function decayPeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The decay period duration

grantVotingUnits

Grants voting units to the specified account. Only the contract owner can mint new tokens and grant additional voting units. Updates the last participation timestamp to start the stable period.

function grantVotingUnits(address to, uint256 amount) external;

Parameters

NameTypeDescription
toaddressThe address to grant voting units to
amountuint256The amount of voting units to grant

burn

Burns tokens and reduces the voting units associated with the token holder.

function burn(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256The amount of tokens to burn

Events

VotingUnitsGranted

Emitted when voting units are granted to an account.

event VotingUnitsGranted(address indexed account, uint256 amount);

Parameters

NameTypeDescription
accountaddressThe address that received the voting units
amountuint256The amount of voting units granted

VotingUnitsBurned

Emitted when voting units are burned.

event VotingUnitsBurned(address indexed account, uint256 amount);

Parameters

NameTypeDescription
accountaddressThe address that burned the voting units
amountuint256The amount of voting units burned

Errors

TokenSoulbound

Emitted when attempting to transfer a soulbound token.

error TokenSoulbound();

SDG

Git Source

Inherits: IERC7787

Author: nomadbitcoin

This contract implements the EIP-7787 standard proposed by Guilherme Neves (@0xneves) and Rafael Castaneda for governance systems where voting power is non-transferable and decays over time. The system ensures that governance power reflects recent and active participation in the ecosystem by implementing a two-phase decay mechanism:

  1. Stable Period: Voting power remains constant for a fixed duration after each contribution
  2. Decay Period: After the stable period ends, voting power linearly decays until it reaches zero System Rules:
  • Voting power remains stable for the duration of the stable period after each contribution
  • After the stable period ends, voting power linearly decays over the decay period
  • If no new contributions are made during the decay period, voting power reaches zero
  • New contributions reset both the stable and decay periods
  • Lost voting power cannot be recovered without new contributions

*This implementation follows the EIP-7787 specification but uses 'stablePeriod' instead of 'gracePeriod' for clarity. The contract provides the core functionality for calculating voting power with time-based degradation. Requirements:

  • The contract requires stable period and decay period to be configured
  • The contract implements linear decay as specified in EIP-7787*

State Variables

SECONDS_PER_DAY

Number of seconds in a day

uint32 private constant SECONDS_PER_DAY = 86400;

_lastParticipation

Mapping from accounts addresses to their last participation timestamp

mapping(address => uint32) private _lastParticipation;

_stablePeriod

Configuration of the stable and decay periods (in days)

uint32 private _stablePeriod;

_decayPeriod

uint32 private _decayPeriod;

Functions

stablePeriod

Returns the duration of the stable period in days.

function stablePeriod() public view virtual returns (uint256);

Returns

NameTypeDescription
<none>uint256The duration of the stable period in days.

decayPeriod

Returns the duration of the decay period in days.

function decayPeriod() public view virtual returns (uint256);

Returns

NameTypeDescription
<none>uint256The duration of the decay period in days.

accountStats

Returns the raw last participation timestamp of an account without any decay adjustments.

function accountStats(address account) public view virtual returns (uint32);

Parameters

NameTypeDescription
accountaddressThe address to check for last participation

Returns

NameTypeDescription
<none>uint32The timestamp of the last participation

_updateLastParticipation

Updates the last participation timestamp for an account.

function _updateLastParticipation(address account) internal virtual;

Parameters

NameTypeDescription
accountaddressThe address to update the participation timestamp for

_setStablePeriod

Sets a new stable period in days

function _setStablePeriod(uint32 stablePeriod_) internal virtual;

Parameters

NameTypeDescription
stablePeriod_uint32The new stable period duration in days

_setDecayPeriod

Sets a new decay period in days

function _setDecayPeriod(uint32 decayPeriod_) internal virtual;

Parameters

NameTypeDescription
decayPeriod_uint32The new decay period duration in days

balanceOf

Returns the balance of the account with decay applied.

function balanceOf(address account) public view virtual returns (uint256);

Parameters

NameTypeDescription
accountaddressThe address to check the balance for

Returns

NameTypeDescription
<none>uint256The current balance with decay applied

Treasury

Git Source

Inherits: ERC20, ITreasury

Implementation of a single-asset treasury that manages deposits and withdrawals

This contract extends ERC20 to implement a treasury system for a single underlying asset

State Variables

_asset

The single underlying asset token managed by this treasury

IERC20 private immutable _asset;

_valocracy

The Valocracy contract address that controls deposits

address private _valocracy;

Functions

constructor

Initializes the contract by setting a name and a symbol for the treasury shares. Also sets the Valocracy contract and the single underlying asset token.

constructor(IERC20 asset_, address valocracy, string memory name, string memory symbol) ERC20(name, symbol);

Parameters

NameTypeDescription
asset_IERC20The single underlying asset token to be managed
valocracyaddressThe address of the Valocracy contract that controls deposits
namestringThe name of the treasury shares
symbolstringThe symbol of the treasury shares

asset

Returns the address of the single underlying asset token.

function asset() public view virtual returns (address);

Returns

NameTypeDescription
<none>addressThe address of the asset token

totalAssets

Returns the total amount of the single asset held by the treasury.

function totalAssets() public view virtual returns (uint256);

Returns

NameTypeDescription
<none>uint256The total balance of the underlying asset

previewWithdraw

Calculates the amount of the underlying asset that would be returned for burning the given amount of shares. The calculation is based on the proportion of total assets to total shares. For example, if there are 2000 assets and 1000 shares, each share represents 2 assets.

function previewWithdraw(uint256 shares) public view virtual returns (uint256);

Parameters

NameTypeDescription
sharesuint256The amount of shares to calculate assets for

Returns

NameTypeDescription
<none>uint256The amount of the underlying asset that would be returned

deposit

Deposits the underlying asset into the treasury and mints shares to the receiver. Only callable by the Valocracy contract.

function deposit(address receiver, uint256 shares) public;

Parameters

NameTypeDescription
receiveraddressThe address that will receive the shares
sharesuint256The amount of shares to mint

withdraw

Withdraws the underlying asset from the treasury by burning shares. Transfers the corresponding amount of the underlying asset to the receiver.

function withdraw(address receiver, uint256 shares) public;

Parameters

NameTypeDescription
receiveraddressThe address that will receive the underlying asset
sharesuint256The amount of shares to burn

Valocracy

Git Source

Inherits: ERC20Votes, Ownable, SDG

Implementation of the EIP-7787 Soulbound Degradable Governance standard using ERC20 tokens

This contract extends ERC20Votes to implement non-transferable tokens with decaying voting power

State Variables

SECONDS_PER_DAY

Number of seconds in a day

uint32 private constant SECONDS_PER_DAY = 86400;

_lastParticipation

Mapping from accounts addresses to their last participation timestamp

mapping(address => uint32) private _lastParticipation;

Functions

constructor

Initializes the contract by setting a name and a symbol. Sets default stable and decay periods to 90 days each.

constructor(string memory name, string memory symbol)
    ERC20(name, symbol)
    ERC20Votes()
    Ownable(msg.sender)
    EIP712(name, "1");

Parameters

NameTypeDescription
namestringThe name of the token
symbolstringThe symbol of the token

tokenURI

Returns the token URI for a given token ID.

function tokenURI(uint256 tokenId) public view returns (string memory);

Parameters

NameTypeDescription
tokenIduint256The ID of the token

Returns

NameTypeDescription
<none>stringThe token URI

_update

Overrides the ERC20Votes-_update to make the token soulbound. Only allows minting and burning, prevents transfers between accounts.

function _update(address from, address to, uint256 value) internal virtual override;

Parameters

NameTypeDescription
fromaddressThe address sending the tokens
toaddressThe address receiving the tokens
valueuint256The amount of tokens

balanceOf

*Returns the balance of account with decay applied. Implements the EIP-7787 decay mechanism:

  • Full balance during stable period
  • Linear decay during decay period
  • Zero balance after decay period ends*
function balanceOf(address account) public view override(ERC20, SDG) returns (uint256);

Parameters

NameTypeDescription
accountaddressThe address to check the balance for

Returns

NameTypeDescription
<none>uint256The current balance with decay applied

_getVotingUnits

Returns the voting units for an account.

function _getVotingUnits(address account) internal view override returns (uint256);

Parameters

NameTypeDescription
accountaddressThe address to check voting units for

Returns

NameTypeDescription
<none>uint256The current voting units

grantVotingUnits

Grants voting units to the specified account by amount. Only the contract owner can mint new tokens and grant additional voting units. Updates the last participation timestamp to start the stable period.

function grantVotingUnits(address to, uint256 amount) public onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to grant voting units to
amountuint256The amount of voting units to grant

burn

Burns tokens and reduces the voting units associated with the token holder.

function burn(uint256 amount) public virtual;

Parameters

NameTypeDescription
amountuint256The amount of tokens to burn