Use cases
Explore
Docs
Pricing

Organigram Protocol

The Organigram Protocol is a Solidity framework for building incorruptible governance systems on Ethereum.

By assembling three simple concepts, it allows for the automated execution of any business rules in a decentralized and auditable manner:

For comprehensive documentation, please visit our official website.

Installation

Install the NPM package with:


# npm:
npm install @organigram/protocol
# pnpm:
pnpm add @organigram/protocol

Usage

With this package, you can directly interact with the Organigram Protocol smart contracts in your Solidity and JavaScript code, or use our official clients to build your own applications on top of the protocol.

Development

Install Foundry

This package uses Foundry (Forge/Anvil) for local development. Install the Foundry toolchain with:


curl -L https://foundry.paradigm.xyz | bash
foundryup

Start local node

Start a local node for development with Anvil:


pnpm anvil

Compile contracts

Compile the contracts with:


pnpm build

Deploy contracts

Deploy protocol contracts to a list of networks:


pnpm deploy:protocol <comma-separated list of network names or chain ids>

Requires a .env with MNEMONIC and NEXT_PUBLIC_THIRDWEB_CLIENT_ID. The deployer account must have enough funds on each target network to cover deployment costs.

For example:


pnpm deploy:protocol mainnet,base,11155111

To deploy to the local Anvil node:


pnpm deploy:protocol anvil

By default, network RPC URLs are built from Thirdweb. You can override a specific network with RPC_URL_<chain id>, or RPC_URL_<network name>, for example RPC_URL_11155111.

The deployment script will also accept an optional --resume flag to resume the last run if the deployment has failed.

Contributing

We are looking for Solidity developers and testers to keep our contracts secure and up-to-date. Please create issues in our Github page, fork and create Pull-Requests, or contact us on our Discord or at hello@organigram.ai.

Client

The OrganigramClient contract is the entry point of the protocol on each chain. It keeps the registry of procedure types and deploys organs, assets and procedures as clones of their implementations, one by one or as a whole organigram in a single transaction. A clone address depends on its salt and on the account deploying it, so that nobody can take an address someone else predicted.

OrganigramClient

Entry point of the protocol on a chain: the registry of procedure types, and the factory of organs, assets and procedures, deployed as clones of their implementations.

Constructor

constructor(string cid, address trustedForwarder, bytes32 salt);

OrganigramClient.asset

Implementation that assets are cloned from.

Signature

function asset() view returns (address);

OrganigramClient.deployAsset

Deploy a single asset clone and initialize it as an ERC-20 token.

Signature

function deployAsset(string name, string symbol, uint256 initialSupply, bytes32 salt) returns (address clone);

Parameters

NameTypeDescription
namestringToken name.
symbolstringToken symbol.
initialSupplyuint256Initial token supply minted to the caller.
saltbytes32Deterministic clone salt.
Returns
NameTypeDescription
cloneaddressAddress of the deployed asset clone.

OrganigramClient.deployAssets

Deploy several asset clones in one call.

Signature

function deployAssets((string, string, uint256, bytes32, bool, address)[] batch) returns (address[] clones);

Parameters

NameTypeDescription
batch(string, string, uint256, bytes32, bool, address)[]Asset deployment payloads.
Returns
NameTypeDescription
clonesaddress[]Addresses of the deployed asset clones.

OrganigramClient.deployOrgan

Deploy a single organ clone and initialize it.

Signature

function deployOrgan(address[] _permissionAddresses, bytes2[] _permissionValues, string cid, (address, string)[] entries, bytes32 salt) returns (address clone);

Parameters

NameTypeDescription
_permissionAddressesaddress[]Addresses receiving permissions on the organ.
_permissionValuesbytes2[]Permission bitmasks aligned with _permissionAddresses.
cidstringMetadata CID assigned to the deployed organ.
entries(address, string)[]Initial entries stored on the organ.
saltbytes32Deterministic clone salt.
Returns
NameTypeDescription
cloneaddressAddress of the deployed organ clone.

OrganigramClient.deployOrganigram

Deploy a complete organigram in one transaction.

Signature

function deployOrganigram((address[], bytes2[], string, (address, string)[], bytes32)[] organBatch, (string, string, uint256, bytes32, bool, address)[] assetBatch, (address, bytes, bytes32)[] procedureBatch) returns (address[] organsDeployed, address[] assetsDeployed, address[] proceduresDeployed);

Parameters

NameTypeDescription
organBatch(address[], bytes2[], string, (address, string)[], bytes32)[]Organ deployment payloads.
assetBatch(string, string, uint256, bytes32, bool, address)[]Asset deployment payloads.
procedureBatch(address, bytes, bytes32)[]Procedure deployment payloads.
Returns
NameTypeDescription
organsDeployedaddress[]Addresses of the deployed organs.
assetsDeployedaddress[]Addresses of the deployed assets.
proceduresDeployedaddress[]Addresses of the deployed procedures.

OrganigramClient.deployOrgans

Deploy several organ clones in one call.

Signature

function deployOrgans((address[], bytes2[], string, (address, string)[], bytes32)[] batch) returns (address[] clones);

Parameters

NameTypeDescription
batch(address[], bytes2[], string, (address, string)[], bytes32)[]Organ deployment payloads.
Returns
NameTypeDescription
clonesaddress[]Addresses of the deployed organ clones.

OrganigramClient.deployProcedure

Deploy one procedure clone from a registered procedure implementation.

Signature

function deployProcedure(address procedureType, bytes data, bytes32 salt) returns (address procedure);

Parameters

NameTypeDescription
procedureTypeaddressRegistered procedure implementation to clone.
databytesOptional initialization calldata executed immediately after deployment.
saltbytes32Deterministic clone salt.
Returns
NameTypeDescription
procedureaddressAddress of the deployed procedure clone.

OrganigramClient.deployProcedures

Deploy several procedure clones in one call.

Signature

function deployProcedures((address, bytes, bytes32)[] batch) returns (address[] created);

Parameters

NameTypeDescription
batch(address, bytes, bytes32)[]Procedure deployment payloads.
Returns
NameTypeDescription
createdaddress[]Addresses of the deployed procedure clones.

OrganigramClient.equityToken

Implementation that equity tokens are cloned from.

Signature

function equityToken() view returns (address);

OrganigramClient.isTrustedForwarder

Return whether an address is the trusted ERC-2771 forwarder.

Signature

function isTrustedForwarder(address forwarder) view returns (bool);

Parameters

NameTypeDescription
forwarderaddressThe forwarder address to test.

OrganigramClient.organ

Implementation that organs are cloned from.

Signature

function organ() view returns (address);

OrganigramClient.owner

Account allowed to register procedure types.

Signature

function owner() view returns (address);

OrganigramClient.proceduresRegistry

Organ listing the registered procedure types.

Signature

function proceduresRegistry() view returns (address);

OrganigramClient.registerProcedures

Register supported procedure implementations in the procedures registry.

Signature

function registerProcedures((address, string)[] entries);

Parameters

NameTypeDescription
entries(address, string)[]Registry entries that point to valid procedure implementations.

OrganigramClient.trustedForwarder

Return the trusted ERC-2771 forwarder used by this contract.

Signature

function trustedForwarder() view returns (address);

OrganigramClient.assetDeployed

An asset was deployed.

Event

event assetDeployed(address asset);

OrganigramClient.organDeployed

An organ was deployed.

Event

event organDeployed(address organ);

OrganigramClient.procedureDeployed

A procedure was deployed from a registered procedure type.

Event

event procedureDeployed(address procedureType, address procedure);

Organs

An organ is a group: a registry of entries, each an address, a document reference or both, a list of permissions, and a balance of ether and tokens. Every change requires a permission held by the caller. Organs can also call outside contracts, but only the calls listed in their execution whitelist.

Organ

A group of an organization: a registry of entries, each an address, a document reference or both, a list of permissions, and a balance of ether and tokens.

Every change requires a permission held by the caller. In a governed organization, procedures hold those permissions, so that every change goes through a decision.

It has every function and event of IOrgan, and the ones below.

Constructor

constructor();

Organ.initialize

Initialize a freshly cloned organ.

Signature

function initialize(address[] permissionAddresses, bytes2[] permissionValues, string cid, (address, string)[] entries, address forwarder);

Parameters

NameTypeDescription
permissionAddressesaddress[]
permissionValuesbytes2[]
cidstringContent identifier describing the organ metadata.
entries(address, string)[]Initial entries stored on the organ.
forwarderaddress

Organ.isTrustedForwarder

Return whether an address is the trusted ERC-2771 forwarder.

Signature

function isTrustedForwarder(address forwarder) view returns (bool);

Parameters

NameTypeDescription
forwarderaddressThe forwarder address to test.

Organ.onERC1155BatchReceived

ERC-1155 hook accepting tokens. ERC-1155 tokens are not recorded by the organ.

Signature

function onERC1155BatchReceived(address arg0, address arg1, uint256[] arg2, uint256[] arg3, bytes arg4) returns (bytes4);

Organ.onERC1155Received

ERC-1155 hook accepting a token. ERC-1155 tokens are not recorded by the organ.

Signature

function onERC1155Received(address arg0, address arg1, uint256 arg2, uint256 arg3, bytes arg4) returns (bytes4);

Organ.onERC721Received

ERC-721 hook recording a token sent to the organ.

Signature

function onERC721Received(address operator, address from, uint256 tokenId, bytes arg3) returns (bytes4);

Organ.supportsInterface

Tell whether the organ supports an interface: ERC-165, IOrgan, and the ERC-777, ERC-721 and ERC-1155 receivers.

Signature

function supportsInterface(bytes4 interfaceId) view returns (bool);

Organ.tokensReceived

ERC-777 hook recording tokens sent to the organ.

Signature

function tokensReceived(address operator, address from, address to, uint256 amount, bytes arg4, bytes arg5);

Organ.transferCoins

Send ERC-20 tokens held by the organ. Requires the WITHDRAW_COINS permission.

The second parameter is ignored.

Signature

function transferCoins(address token, address arg1, address to, uint256 amount);

Organ.transferCollectible

Send an ERC-721 token held by the organ. Requires the WITHDRAW_COLLECTIBLES permission.

The second parameter is ignored.

Signature

function transferCollectible(address token, address arg1, address to, uint256 tokenId);

Organ.transferEther

Send ether held by the organ. Requires the WITHDRAW_ETHER permission.

Signature

function transferEther(address to, uint256 value);

Organ.trustedForwarder

Return the trusted ERC-2771 forwarder used by this contract.

Signature

function trustedForwarder() view returns (address);

Organ.etherTransferred

The organ sent ether.

Event

event etherTransferred(address from, address to, uint256 amount);

Organ.Initialized

Triggered when the contract has been initialized or reinitialized.

Event

event Initialized(uint64 version);

IOrgan

The functions organs expose to procedures and applications: entries, permissions, metadata and whitelisted calls.

IOrgan.addEntries

Append entries to the organ directory.

Signature

function addEntries((address, string)[] entries) returns (uint256[] indexes);

Parameters

NameTypeDescription
entries(address, string)[]Entries to append.
Returns
NameTypeDescription
indexesuint256[]Indexes assigned to the newly inserted entries.

IOrgan.addPermission

Grant permissions to one address or procedure.

Signature

function addPermission(address permissionAddress, bytes2 permissionValue);

Parameters

NameTypeDescription
permissionAddressaddressAddress receiving the permission bitmask.
permissionValuebytes2Permission bitmask to grant.

IOrgan.executeWhitelisted

Execute an external call that has been approved by a whitelist policy.

The organ validates the call against the policy configured for target + selector before forwarding the call. Every configured constraint must pass.

Signature

function executeWhitelisted(address target, uint256 value, bytes data) returns (bytes result);

Parameters

NameTypeDescription
targetaddressThe external contract to call.
valueuint256The amount of native token to forward with the call.
databytesThe encoded calldata forwarded to target.
Returns
NameTypeDescription
resultbytesThe raw return data produced by the external call.

IOrgan.getCallPolicy

Return summary information about a call policy.

Signature

function getCallPolicy(address target, bytes4 selector) view returns (bool enabled, uint256 constraintsLength, uint256 whitelistedAddressesLength);

Parameters

NameTypeDescription
targetaddressThe external contract keyed by the policy.
selectorbytes4The function selector keyed by the policy.
Returns
NameTypeDescription
enabledboolWhether the policy exists and is active.
constraintsLengthuint256The number of parameter constraints configured on the policy.
whitelistedAddressesLengthuint256The number of addresses stored in the policy whitelist.

IOrgan.getCallPolicyConstraint

Return one parameter constraint of a call policy.

Signature

function getCallPolicyConstraint(address target, bytes4 selector, uint256 index) view returns (uint8 paramIndex, uint8 constraintType, bytes32 minValue, bytes32 maxValue, bytes32 exactValue);

Parameters

NameTypeDescription
targetaddressThe external contract keyed by the policy.
selectorbytes4The function selector keyed by the policy.
indexuint256The position of the constraint inside the policy.
Returns
NameTypeDescription
paramIndexuint8The zero-based calldata argument index constrained by this rule.
constraintTypeuint8The type of validation applied to that argument.
minValuebytes32The lower bound used by range constraints.
maxValuebytes32The upper bound used by range constraints.
exactValuebytes32The exact value used by exact-match constraints.

IOrgan.getEntry

Return one stored entry.

Signature

function getEntry(uint256 index) view returns ((address, string) entry);

Parameters

NameTypeDescription
indexuint256Index of the entry to read.
Returns
NameTypeDescription
entry(address, string)Entry payload stored at index.

IOrgan.getEntryIndexForAddress

Find the index of one entry address.

Signature

function getEntryIndexForAddress(address addr) view returns (uint256 index);

Parameters

NameTypeDescription
addraddressAddress stored in the entry.
Returns
NameTypeDescription
indexuint256Index of the entry associated with addr.

IOrgan.getOrgan

Return the core summary of the organ.

Signature

function getOrgan() view returns (string cid, uint256 permissionsLength, uint256 entriesLength, uint256 entriesCount, bytes4 interfaceId);

Returns

NameTypeDescription
cidstringMetadata CID currently attached to the organ.
permissionsLengthuint256Number of permission entries configured on the organ.
entriesLengthuint256Number of allocated entry slots.
entriesCountuint256Number of active entries.
interfaceIdbytes4ERC-165 interface id implemented by the organ.

IOrgan.getPermission

Return one permission entry by index.

Signature

function getPermission(uint256 index) view returns (address addr, bytes2 perms);

Parameters

NameTypeDescription
indexuint256Index of the permission entry to read.
Returns
NameTypeDescription
addraddressAddress holding the permission.
permsbytes2Permission bitmask held by addr.

IOrgan.getPermissions

Return the permission bitmask assigned to one address.

Signature

function getPermissions(address addr) view returns (bytes2 perms);

Parameters

NameTypeDescription
addraddressAddress to inspect.
Returns
NameTypeDescription
permsbytes2Permission bitmask currently assigned to addr.

IOrgan.initialize

Initialize a freshly cloned organ.

Signature

function initialize(address[] procedures, bytes2[] permissions, string cid, (address, string)[] entries, address trustedForwarder);

Parameters

NameTypeDescription
proceduresaddress[]Addresses that receive permissions on the organ.
permissionsbytes2[]Permission bitmasks aligned with procedures.
cidstringContent identifier describing the organ metadata.
entries(address, string)[]Initial entries stored on the organ.
trustedForwarderaddressERC-2771 forwarder trusted by the organ.

IOrgan.isCallPolicyWhitelistedAddress

Check whether an address is present in a call policy whitelist.

Signature

function isCallPolicyWhitelistedAddress(address target, bytes4 selector, address candidate) view returns (bool);

Parameters

NameTypeDescription
targetaddressThe external contract keyed by the policy.
selectorbytes4The function selector keyed by the policy.
candidateaddressThe address to test against the whitelist.

IOrgan.removeCallPolicy

Remove a previously configured external call policy.

Signature

function removeCallPolicy(address target, bytes4 selector);

Parameters

NameTypeDescription
targetaddressThe external contract whose policy should be removed.
selectorbytes4The function selector whose policy should be removed.

IOrgan.removeEntries

Remove entries from the organ directory.

Signature

function removeEntries(uint256[] indexes);

Parameters

NameTypeDescription
indexesuint256[]Indexes to remove.

IOrgan.removePermission

Remove every permission bit from one address or procedure.

Signature

function removePermission(address permissionAddress);

Parameters

NameTypeDescription
permissionAddressaddressAddress whose permissions should be removed.

IOrgan.replaceEntry

Replace one entry at a fixed index.

Signature

function replaceEntry(uint256 index, (address, string) entry);

Parameters

NameTypeDescription
indexuint256Index of the entry to replace.
entry(address, string)New entry payload stored at index.

IOrgan.replacePermission

Replace one permission holder with another.

Signature

function replacePermission(address oldPermission, address newPermission, bytes2 newPermissionValue);

Parameters

NameTypeDescription
oldPermissionaddressAddress currently holding the permission.
newPermissionaddressAddress that should receive the permission instead.
newPermissionValuebytes2Permission bitmask assigned to newPermission.

IOrgan.setCallPolicy

Configure a whitelist policy for an external call path.

Policies are keyed by target + selector. Each policy can constrain calldata arguments with NONE, EXACT, RANGE, SELF, or WHITELISTED_ADDRESS. The whitelist is only consulted by constraints that use WHITELISTED_ADDRESS.

Signature

function setCallPolicy(address target, bytes4 selector, (uint8, uint8, bytes32, bytes32, bytes32)[] constraints, address[] whitelistedAddresses);

Parameters

NameTypeDescription
targetaddressThe external contract the organ may call.
selectorbytes4The function selector allowed on target.
constraints(uint8, uint8, bytes32, bytes32, bytes32)[]The calldata constraints that must be satisfied to execute the call.
whitelistedAddressesaddress[]The addresses accepted by whitelist-based constraints.

IOrgan.updateCid

Update the metadata CID of the organ.

Signature

function updateCid(string cid);

Parameters

NameTypeDescription
cidstringNew content identifier describing the organ.

OrganLibrary

Storage layout and rules of organs, linked into the Organ contract.

OrganLibrary.PERMISSION_ADD_ENTRIES

Permission to add entries.

Signature

function PERMISSION_ADD_ENTRIES() view returns (bytes2);

OrganLibrary.PERMISSION_ADD_PERMISSIONS

Permission to grant permissions.

Signature

function PERMISSION_ADD_PERMISSIONS() view returns (bytes2);

OrganLibrary.PERMISSION_EXECUTE_WHITELISTED

Permission to make the organ call a whitelisted outside contract.

Signature

function PERMISSION_EXECUTE_WHITELISTED() view returns (bytes2);

OrganLibrary.PERMISSION_MANAGE_EXECUTION_WHITELIST

Permission to change the calls the organ may make to outside contracts.

Signature

function PERMISSION_MANAGE_EXECUTION_WHITELIST() view returns (bytes2);

OrganLibrary.PERMISSION_REMOVE_ENTRIES

Permission to remove entries.

Signature

function PERMISSION_REMOVE_ENTRIES() view returns (bytes2);

OrganLibrary.PERMISSION_REMOVE_PERMISSIONS

Permission to revoke permissions.

Signature

function PERMISSION_REMOVE_PERMISSIONS() view returns (bytes2);

OrganLibrary.PERMISSION_UPDATE_METADATA

Permission to replace the metadata reference.

Signature

function PERMISSION_UPDATE_METADATA() view returns (bytes2);

OrganLibrary.PERMISSION_WITHDRAW_COINS

Permission to send tokens held by the organ.

Signature

function PERMISSION_WITHDRAW_COINS() view returns (bytes2);

OrganLibrary.PERMISSION_WITHDRAW_COLLECTIBLES

Permission to send ERC-721 tokens held by the organ.

Signature

function PERMISSION_WITHDRAW_COLLECTIBLES() view returns (bytes2);

OrganLibrary.PERMISSION_WITHDRAW_ETHER

Permission to send ether held by the organ.

Signature

function PERMISSION_WITHDRAW_ETHER() view returns (bytes2);

OrganLibrary.callPolicyRemoved

The organ may no longer call a function of an outside contract.

Event

event callPolicyRemoved(address indexed caller, address indexed target, bytes4 indexed selector);

OrganLibrary.callPolicySet

The organ may now call a function of an outside contract.

Event

event callPolicySet(address indexed caller, address indexed target, bytes4 indexed selector);

OrganLibrary.callPolicyWhitelistedAddressAdded

An address was allowed as an argument of a whitelisted call.

Event

event callPolicyWhitelistedAddressAdded(bytes32 indexed policyKey, address indexed candidate);

OrganLibrary.callPolicyWhitelistedAddressRemoved

An address is no longer allowed as an argument of a whitelisted call.

Event

event callPolicyWhitelistedAddressRemoved(bytes32 indexed policyKey, address indexed candidate);

OrganLibrary.cidUpdated

The metadata reference of the organ changed.

Event

event cidUpdated(address from, string cid);

OrganLibrary.coinsReceived

The organ received tokens.

Event

event coinsReceived(address operator, address from, address to, uint256 amount);

OrganLibrary.coinsTransferred

The organ sent tokens.

Event

event coinsTransferred(address operator, address from, address to, uint256 amount);

OrganLibrary.collectibleReceived

The organ received an ERC-721 token.

Event

event collectibleReceived(address operator, address from, uint256 tokenId);

OrganLibrary.collectibleTransferred

The organ sent an ERC-721 token.

Event

event collectibleTransferred(address operator, address to, uint256 tokenId);

OrganLibrary.entryAdded

An entry was added to the organ.

Event

event entryAdded(address from, uint256 index, address addr, string cid);

OrganLibrary.entryRemoved

An entry was removed from the organ.

Event

event entryRemoved(address from, uint256 index);

OrganLibrary.etherReceived

The organ received ether.

Event

event etherReceived(address from, uint256 amount);

OrganLibrary.etherTransferred

The organ sent ether.

Event

event etherTransferred(address from, address to, uint256 amount);

OrganLibrary.permissionAdded

An address received permissions on the organ.

Event

event permissionAdded(address from, address permissionAddress, bytes2 permissionValue);

OrganLibrary.permissionRemoved

An address lost its permissions on the organ.

Event

event permissionRemoved(address from, address permissionAddress);

OrganLibrary.whitelistedExecution

The organ made a whitelisted call to an outside contract.

Event

event whitelistedExecution(address indexed caller, address indexed target, bytes4 indexed selector, uint256 value);

Procedures

A procedure lets the members of some organs change other organs through proposals. Proposers submit a list of operations; with moderation, moderators present or block it; deciders adopt or reject it, and adoption runs the operations. Every action has a …BySig variant that verifies an EIP-712 signature, so that a relayer can submit it on behalf of the signer.

Procedure

Lets the members of some organs change other organs through proposals: lists of operations that proposers submit, moderators may present or block, and deciders adopt or reject.

Adoption runs the operations. Every action has a …BySig variant verifying an EIP-712 signature, so that a relayer can submit it on behalf of the signer.

Constructor

constructor();

Procedure.applyProposal

Apply proposal.

Signature

function applyProposal(uint256 proposalKey);

Procedure.applyProposalBySig

Settle a proposal with an application signed by any account, relayed by another.

Signature

function applyProposalBySig(uint256 proposalKey, uint256 nonce, uint256 deadline, bytes signature);

Procedure.blockProposal

Block a proposal as a moderator, with a reason.

Signature

function blockProposal(uint256 proposalKey, string reason);

Procedure.blockProposalBySig

Block a proposal with a block signed by a moderator, relayed by any account.

Signature

function blockProposalBySig(uint256 proposalKey, string reason, uint256 nonce, uint256 deadline, bytes signature);

Procedure.eip712Domain

returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.

Signature

function eip712Domain() view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions);

Procedure.getExecutionContext

Lets an operation target safely identify the proposal currently being applied.

Signature

function getExecutionContext() view returns (bool isApplying, uint256 proposalKey, address proposalCreator);

Procedure.getNonce

Read the next signature nonce of an account.

Signature

function getNonce(address account) view returns (uint256);

Procedure.getProcedure

Read the metadata reference, the roles and the proposal count of the procedure.

Signature

function getProcedure() view returns (string cid, address proposers, address moderators, address deciders, bool withModeration, uint256 proposalsLength, bytes4 interfaceId);

Procedure.getProposal

Read one proposal.

Signature

function getProposal(uint256 proposalKey) view returns ((address, string, string, bool, bool, bool, bool, (uint256, address, bytes, uint256, bool)[]));

Procedure.initialize

Initialize a procedure clone with its roles.

Signature

function initialize(string _cid, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder);

Parameters

NameTypeDescription
_cidstringReference to the procedure metadata.
_proposersaddressOrgan whose members may submit proposals, or a single address.
_moderatorsaddressOrgan whose members may present or block proposals.
_decidersaddressOrgan whose members adopt or reject proposals, or a single address.
_withModerationboolWhether proposals must be presented by a moderator before the decision.
_trustedForwarderaddressForwarder relaying gasless transactions.

Procedure.INTERFACE_ID

ERC-165 interface identifier of procedures.

Signature

function INTERFACE_ID() view returns (bytes4);

Procedure.isOwnerBoundProposalOperation

Tell whether an operation may only be proposed by the account it concerns.

Signature

function isOwnerBoundProposalOperation(bytes operationData) pure returns (bool);

Procedure.isTrustedForwarder

Return whether an address is the trusted ERC-2771 forwarder.

Signature

function isTrustedForwarder(address forwarder) view returns (bool);

Parameters

NameTypeDescription
forwarderaddressThe forwarder address to test.

Procedure.presentProposal

When moderation is enabled, moderators must accept the proposal.

Signature

function presentProposal(uint256 proposalKey);

Procedure.presentProposalBySig

Present a proposal with a presentation signed by a moderator, relayed by any account.

Signature

function presentProposalBySig(uint256 proposalKey, uint256 nonce, uint256 deadline, bytes signature);

Procedure.propose

Public API : Proposals creation and update.

Signature

function propose(string cid, (uint256, address, bytes, uint256, bool)[] operations) returns (uint256 proposalKey);

Procedure.proposeBySig

Submit a proposal signed by a proposer, relayed by any account.

Signature

function proposeBySig(string cid, (uint256, address, bytes, uint256, bool)[] operations, uint256 nonce, uint256 deadline, bytes signature) returns (uint256 proposalKey);

Procedure.supportsInterface

Returns true if this contract implements the interface defined by interfaceId. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.

Signature

function supportsInterface(bytes4 interfaceId) view returns (bool);

Procedure.transferEquity

Transfers the proposal creator's equity; the token emits the movement record.

Signature

function transferEquity(address asset, address recipient, uint256 amount, string movementCid);

Procedure.trustedForwarder

Return the trusted ERC-2771 forwarder used by this contract.

Signature

function trustedForwarder() view returns (address);

Procedure.validateProposalCreator

Revert unless the creator of a proposal may propose this operation.

Signature

function validateProposalCreator(address creator, bytes operationData) view;

Procedure.EIP712DomainChanged

MAY be emitted to signal that the domain could have changed.

Event

event EIP712DomainChanged();

Procedure.Initialized

Triggered when the contract has been initialized or reinitialized.

Event

event Initialized(uint64 version);

NominationProcedure

A procedure in which any one member of the deciders organ adopts or rejects a proposal alone.

It has every function and event of Procedure, and the ones below.

NominationProcedure.initialize

Initialize a procedure clone with its roles.

Signature

function initialize(string _cid, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder);

Parameters

NameTypeDescription
_cidstringReference to the procedure metadata.
_proposersaddressOrgan whose members may submit proposals, or a single address.
_moderatorsaddressOrgan whose members may present or block proposals.
_decidersaddressOrgan whose members adopt or reject proposals, or a single address.
_withModerationboolWhether proposals must be presented by a moderator before the decision.
_trustedForwarderaddressForwarder relaying gasless transactions.

NominationProcedure.nominate

Apply the nomination.

Signature

function nominate(uint256 proposalKey);

Parameters

NameTypeDescription
proposalKeyuint256The key used to identify the proposal.

NominationProcedure.nominateBySig

Adopt a proposal with an adoption signed by a decider, relayed by any account.

Signature

function nominateBySig(uint256 proposalKey, uint256 nonce, uint256 deadline, bytes signature);

NominationProcedure.reject

Reject a nomination without applying its proposal operations.

Signature

function reject(uint256 proposalKey);

Parameters

NameTypeDescription
proposalKeyuint256The proposal to reject.

NominationProcedure.ProposalApplied

A proposal was settled.

Event

event ProposalApplied(uint256 indexed proposalKey);

VoteProcedure

A procedure in which the members of the deciders organ vote on each proposal.

The vote opens when a proposal is presented. Once it is over, anyone calls applyProposal to count the ballots and settle the proposal.

It has every function and event of Procedure, and the ones below.

VoteProcedure.count

Count votes when election is ended.

@todo Handle delegation of Votes.

Signature

function count(uint256 proposalKey) view returns (bool approved);

Returns

NameTypeDescription
approvedboolTrue if the proposal is adopted.

VoteProcedure.getElection

Get information about a current election

Signature

function getElection(uint256 _proposalKey) view returns (uint256 start, bool hasVoted, uint256 votesCount);

Returns

NameTypeDescription
startuint256The UNIX time when the election started.
hasVotedboolTrue if the voter has voted.
votesCountuint256The number of votes cast so far.

VoteProcedure.getElectionResults

Get the current vote split and the eligible voting base.

ERC20VoteProcedure overrides this to use snapshot voting power.

Signature

function getElectionResults(uint256 proposalKey) view returns (uint256 approvals, uint256 objections, uint256 eligibleVotes);

Returns

NameTypeDescription
approvalsuint256The number of approving votes.
objectionsuint256The number of rejecting votes.
eligibleVotesuint256The number of votes eligible to participate.

VoteProcedure.initialize

Initialize the procedure.

Signature

function initialize(string _cid, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder, uint32 _quorumSize, uint32 _voteDuration, uint32 _majoritySize);

VoteProcedure.majoritySize

Share of the ballots that must approve, in thousandths of a percent.

Signature

function majoritySize() view returns (uint32);

VoteProcedure.quorumSize

Share of the voters who must vote, in thousandths of a percent.

Signature

function quorumSize() view returns (uint32);

VoteProcedure.vote

Create a election.

Signature

function vote(uint256 proposalKey, bool approval);

VoteProcedure.voteBySig

Cast a vote signed by a decider, relayed by any account.

Signature

function voteBySig(uint256 proposalKey, bool approval, uint256 nonce, uint256 deadline, bytes signature);

VoteProcedure.voteDuration

Duration of a vote, in seconds.

Signature

function voteDuration() view returns (uint32);

VoteProcedure.ProposalApplied

A proposal was settled.

Event

event ProposalApplied(uint256 indexed proposalKey);

VoteProcedure.ProposalBlocked

A moderator blocked a proposal.

Event

event ProposalBlocked(address indexed moderator, uint256 indexed proposalKey, string reason);

VoteProcedure.ProposalCreated

A proposal was submitted.

Event

event ProposalCreated(address indexed creator, uint256 indexed proposalKey);

VoteProcedure.ProposalPresented

A moderator presented a proposal to the deciders.

Event

event ProposalPresented(address indexed presenter, uint256 indexed proposalKey);

ERC20VoteProcedure

A vote procedure in which each ballot weighs the token balance of the voter.

Ballots weigh balances held just before the vote opened, so tokens moved during the vote do not count twice.

It has every function and event of VoteProcedure, and the ones below.

ERC20VoteProcedure.initialize

Initialize an ERC-20 vote whose roles are held by organ members, token holders or nobody.

Signature

function initialize(string _metadata, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder, uint32 _quorumSize, uint32 _voteDuration, uint32 _majoritySize, address _tokenContract, uint8[3] _roleModes);

Parameters

NameTypeDescription
_metadatastring
_proposersaddress
_moderatorsaddress
_decidersaddress
_withModerationbool
_trustedForwarderaddress
_quorumSizeuint32
_voteDurationuint32
_majoritySizeuint32
_tokenContractaddress
_roleModesuint8[3]Role modes of the proposers, moderators and voters.

ERC20VoteProcedure.initialize

Initialize the procedure.

Signature

function initialize(string _metadata, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder, uint32 _quorumSize, uint32 _voteDuration, uint32 _majoritySize, address _tokenContract);

Parameters

NameTypeDescription
_metadatastringThe procedure metadata.
_proposersaddressThe organ whose entries will be allowed to propose proposals.
_moderatorsaddressThe organ whose entries will be allowed to moderate proposals.
_decidersaddressThe organ whose entries will be allowed to adopt or refect proposals.
_withModerationboolWhether or not the procedure requires moderation.
_trustedForwarderaddressThe trusted forwarder contract.
_quorumSizeuint32The minimum percentage of votes required to validate a election.
_voteDurationuint32Duration of vote in seconds.
_majoritySizeuint32The minimum percentage of votes required to validate a election.
_tokenContractaddressThe ERC20 token contract representing the rights to vote.

ERC20VoteProcedure.initialize

Initialize an ERC-20 vote with optional member-majority validation.

Signature

function initialize(string _metadata, address _proposers, address _moderators, address _deciders, bool _withModeration, address _trustedForwarder, uint32 _quorumSize, uint32 _voteDuration, uint32 _majoritySize, address _tokenContract, uint8[3] _roleModes, bool _requireMemberMajority);

ERC20VoteProcedure.moderatorMode

Whether moderators are organ members, token holders, or nobody.

Signature

function moderatorMode() view returns (uint8);

ERC20VoteProcedure.proposerMode

Whether proposers are organ members, token holders, or nobody.

Signature

function proposerMode() view returns (uint8);

ERC20VoteProcedure.requireMemberMajority

When voters come from an organ, require a majority of its members in addition to the usual token-weighted quorum and majority.

Signature

function requireMemberMajority() view returns (bool);

ERC20VoteProcedure.tokenContract

tokenContract is an ERC20Votes-compatible token representing the rights to vote.

Signature

function tokenContract() view returns (address);

ERC20VoteProcedure.voterMode

Whether voters are organ members or token holders.

Signature

function voterMode() view returns (uint8);

ProcedureLibrary

Storage layout and rules of proposals, linked into procedure contracts.

ProcedureLibrary.isInOrgan

Utils.

Signature

function isInOrgan(address organ, address caller) view returns (bool);

ProcedureLibrary.ProposalApplied

A proposal was settled.

Event

event ProposalApplied(uint256 indexed proposalKey);

ProcedureLibrary.ProposalBlocked

A moderator blocked a proposal.

Event

event ProposalBlocked(address indexed moderator, uint256 indexed proposalKey, string reason);

ProcedureLibrary.ProposalCreated

A proposal was submitted.

Event

event ProposalCreated(address indexed creator, uint256 indexed proposalKey);

ProcedureLibrary.ProposalPresented

A moderator presented a proposal to the deciders.

Event

event ProposalPresented(address indexed presenter, uint256 indexed proposalKey);

Assets

Assets are ERC-20 tokens with voting checkpoints, so that a vote can weigh balances at a past moment. An EquityToken represents company shares: its transfers must be approved by a procedure.

Asset

An ERC-20 token with voting checkpoints, held by organs.

Constructor

constructor();

Asset.allowance

Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.

Signature

function allowance(address owner, address spender) view returns (uint256);

Asset.approve

See {IERC20-approve}. NOTE: If value is the maximum uint256, the allowance is not updated on transferFrom. This is semantically equivalent to an infinite approval. Requirements: - spender cannot be the zero address.

Signature

function approve(address spender, uint256 value) returns (bool);

Asset.balanceOf

Returns the value of tokens owned by account.

Signature

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

Asset.checkpoints

Get the pos-th checkpoint for account.

Signature

function checkpoints(address account, uint32 pos) view returns ((uint48, uint208));

Asset.clock

Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting), in which case {CLOCK_MODE} should be overridden as well to match.

Signature

function clock() view returns (uint48);

Asset.CLOCK_MODE

Machine-readable description of the clock as specified in ERC-6372.

Signature

function CLOCK_MODE() view returns (string);

Asset.decimals

Returns the number of decimals used to get its user representation. For example, if decimals equals 2, a balance of 505 tokens should be displayed to a user as 5.05 (505 / 10 ** 2). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for display purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.

Signature

function decimals() view returns (uint8);

Asset.delegate

Delegates votes from the sender to delegatee.

Signature

function delegate(address delegatee);

Asset.delegateBySig

Delegates votes from signer to delegatee.

Signature

function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s);

Asset.delegates

Returns the delegate that account has chosen.

Signature

function delegates(address account) view returns (address);

Asset.eip712Domain

returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.

Signature

function eip712Domain() view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions);

Asset.getPastTotalSupply

Returns the total supply of votes available at a specific moment in the past. If the clock() is configured to use block numbers, this will return the value at the end of the corresponding block. NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote. Requirements: - timepoint must be in the past. If operating using block numbers, the block must be already mined.

Signature

function getPastTotalSupply(uint256 timepoint) view returns (uint256);

Asset.getPastVotes

Returns the amount of votes that account had at a specific moment in the past. If the clock() is configured to use block numbers, this will return the value at the end of the corresponding block. Requirements: - timepoint must be in the past. If operating using block numbers, the block must be already mined.

Signature

function getPastVotes(address account, uint256 timepoint) view returns (uint256);

Asset.getVotes

Returns the current amount of votes that account has.

Signature

function getVotes(address account) view returns (uint256);

Asset.initialize

Initialize an asset clone and mint its supply.

Signature

function initialize(string name_, string symbol_, address initialReceiver_, uint256 initialSupply_);

Parameters

NameTypeDescription
name_stringToken name.
symbol_stringToken symbol.
initialReceiver_addressAccount receiving the initial supply.
initialSupply_uint256Supply minted at initialization.

Asset.name

Returns the name of the token.

Signature

function name() view returns (string);

Asset.nonces

Returns the next unused nonce for an address.

Signature

function nonces(address owner) view returns (uint256);

Asset.numCheckpoints

Get number of checkpoints for account.

Signature

function numCheckpoints(address account) view returns (uint32);

Asset.symbol

Returns the symbol of the token, usually a shorter version of the name.

Signature

function symbol() view returns (string);

Asset.totalSupply

Returns the value of tokens in existence.

Signature

function totalSupply() view returns (uint256);

Asset.transfer

See {IERC20-transfer}. Requirements: - to cannot be the zero address. - the caller must have a balance of at least value.

Signature

function transfer(address to, uint256 value) returns (bool);

Asset.transferFrom

See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum uint256. Requirements: - from and to cannot be the zero address. - from must have a balance of at least value. - the caller must have allowance for from's tokens of at least value.

Signature

function transferFrom(address from, address to, uint256 value) returns (bool);

Asset.Approval

Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.

Event

event Approval(address indexed owner, address indexed spender, uint256 value);

Asset.DelegateChanged

Emitted when an account changes their delegate.

Event

event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

Asset.DelegateVotesChanged

Emitted when a token transfer or delegate change results in changes to a delegate's number of voting units.

Event

event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes);

Asset.EIP712DomainChanged

MAY be emitted to signal that the domain could have changed.

Event

event EIP712DomainChanged();

Asset.Initialized

Triggered when the contract has been initialized or reinitialized.

Event

event Initialized(uint64 version);

Asset.Transfer

Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.

Event

event Transfer(address indexed from, address indexed to, uint256 value);

EquityToken

ERC-20 representation of equity settled by an approved procedure.

It has every function and event of Asset, and the ones below.

Constructor

constructor();

EquityToken.ADMIN_PROCEDURE_ROLE

Role of the procedures that change which procedures hold a role.

Signature

function ADMIN_PROCEDURE_ROLE() view returns (bytes32);

EquityToken.initialize

Initialize an equity token clone and mint its supply.

Signature

function initialize(string name_, string symbol_, address initialHolder_, uint256 initialSupply_, address transferProcedure_);

Parameters

NameTypeDescription
name_stringToken name.
symbol_stringToken symbol.
initialHolder_addressAccount receiving the initial supply.
initialSupply_uint256Supply minted at initialization.
transferProcedure_addressProcedure settling transfers, which also receives the admin role.

EquityToken.isProcedureAuthorized

Tell whether a procedure holds a role.

Signature

function isProcedureAuthorized(bytes32 role, address procedure) view returns (bool);

EquityToken.isTransferProcedure

Tell whether a procedure may settle transfers.

Signature

function isTransferProcedure(address procedure) view returns (bool);

EquityToken.setProcedureAuthorization

Grant or revoke a transfer or administration procedure through governance.

Signature

function setProcedureAuthorization(bytes32 role, address procedure, bool authorized);

EquityToken.settleTransfer

Settles a transfer of the applying proposal's creator and records the movement.

Signature

function settleTransfer(address recipient, uint256 amount, string movementCid);

EquityToken.TRANSFER_PROCEDURE_ROLE

Role of the procedures that settle transfers.

Signature

function TRANSFER_PROCEDURE_ROLE() view returns (bytes32);

EquityToken.validateTransfer

Checks the transfer conditions during proposal creation.

Signature

function validateTransfer(address creator, address recipient, uint256 amount, string movementCid) view;

EquityToken.MovementSettled

Movement record of a settled transfer, from which the register of share movements is built.

Event

event MovementSettled(address indexed procedure, uint256 indexed proposalKey, address indexed seller, address recipient, uint256 amount, string movementCid);

EquityToken.ProcedureAuthorizationUpdated

A procedure received or lost a role.

Event

event ProcedureAuthorizationUpdated(bytes32 indexed role, address indexed procedure, bool authorized);

Gasless transactions

The MetaGasStation is the trusted forwarder of the protocol contracts: it relays transactions signed by users who hold no ether, and the contracts read the original signer instead of the relayer.

MetaGasStation

Trusted forwarder of the protocol contracts: it relays requests signed by accounts that hold no ether, and the contracts read the signer instead of the relayer.

Constructor

constructor(string name);

MetaGasStation.eip712Domain

returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.

Signature

function eip712Domain() view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions);

MetaGasStation.execute

Executes a request on behalf of signature's signer using the ERC-2771 protocol. The gas provided to the requested call may not be exactly the amount requested, but the call will not run out of gas. Will revert if the request is invalid or the call reverts, in this case the nonce is not consumed. Requirements: - The request value should be equal to the provided msg.value. - The request should be valid according to {verify}.

Signature

function execute((address, address, uint256, uint256, uint48, bytes, bytes) request) payable;

MetaGasStation.executeBatch

Batch version of {execute} with optional refunding and atomic execution. In case a batch contains at least one invalid request (see {verify}), the request will be skipped and the refundReceiver parameter will receive back the unused requested value at the end of the execution. This is done to prevent reverting the entire batch when a request is invalid or has already been submitted. If the refundReceiver is the address(0), this function will revert when at least one of the requests was not valid instead of skipping it. This could be useful if a batch is required to get executed atomically (at least at the top-level). For example, refunding (and thus atomicity) can be opt-out if the relayer is using a service that avoids including reverted transactions. Requirements: - The sum of the requests' values should be equal to the provided msg.value. - All of the requests should be valid (see {verify}) when refundReceiver is the zero address. NOTE: Setting a zero refundReceiver guarantees an all-or-nothing requests execution only for the first-level forwarded calls. In case a forwarded request calls to a contract with another subcall, the second-level call may revert without the top-level call reverting.

Signature

function executeBatch((address, address, uint256, uint256, uint48, bytes, bytes)[] requests, address refundReceiver) payable;

MetaGasStation.nonces

Returns the next unused nonce for an address.

Signature

function nonces(address owner) view returns (uint256);

MetaGasStation.verify

Returns true if a request is valid for a provided signature at the current block timestamp. A transaction is considered valid when the target trusts this forwarder, the request hasn't expired (deadline is not met), and the signer matches the from parameter of the signed request. NOTE: A request may return false here but it won't cause {executeBatch} to revert if a refund receiver is provided.

Signature

function verify((address, address, uint256, uint256, uint48, bytes, bytes) request) view returns (bool);

MetaGasStation.EIP712DomainChanged

MAY be emitted to signal that the domain could have changed.

Event

event EIP712DomainChanged();

MetaGasStation.ExecutedForwardRequest

Emitted when a ForwardRequest is executed. NOTE: An unsuccessful forward request could be due to an invalid signature, an expired deadline, or simply a revert in the requested call. The contract guarantees that the relayer is not able to force the requested call to run out of gas.

Event

event ExecutedForwardRequest(address indexed signer, uint256 nonce, bool success);

Edit this page

On this page:

Installation
Install Foundry

Follow us:

© 2026 Organigram SAS

All Rights Reserved.