Skip to content

Specification defining valid Ricardian contracts

License

Notifications You must be signed in to change notification settings

EOSIO/ricardian-spec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 

Repository files navigation

EOSIO.CDT Ricardian Contract Specification EOSIO Alpha

Spec Version: v0.2.0

General Information

In conjunction with Ricardian Template Toolkit, this specification is a new addition to the EOSIO.CDT suite of tooling.

The Ricardian Contract Specification gives a set of requirements that a Ricardian contract should follow in order to be considered valid. Invalid contracts may still work with non-validating user agents, but will not work with user agents which are built with the Ricardian Template Toolkit.

By conforming to a common specification, contracts can be validated and presented in a common way. For instance, Resources must contain a SHA-256 hash value which will allow a validating user agent to check the resource contents and ensure that the resource at the URL has not been altered. Since resources can be used to represent the user or company that is proposing the contract, it is important that the resource URL for the contract is correct and has not been altered since the contract was published.

Ricardian contracts should be written in the English language. The contract itself consists of a set of metadata values supplied in YAML format, followed by the body of the contract, written using a subset of CommonMark with Handlebars-based variable substitution. Future versions may add support for metadata values supplied in JSON format.

Metadata Fields

  • spec_version -- Required
    • Specifies the version of the Ricardian Contract Specification that the contract follows
    • Value is a string in the form of M.m.p, where each version element is an integer representing the MAJOR, MINOR, and PATCH level of the specification being followed
    • May also be specified as M.m, omitting the PATCH level (see below for explanation of compatibility)
    • Implementations which process contracts MUST follow the version interpretation given below
  • title -- Required
    • Provides a user-friendly alternative to the action name, representing the title of the action
    • Must not contain variables
    • Maximum length of 50 characters (but keeping this as short as possible is recommended, as some user agents may truncate longer titles)
  • summary -- Required
    • Provides a brief, user-friendly description of the intent of the action
    • Maximum length of 116 characters
    • May contain variables, but content with expanded variables must be within maximum length
  • icon -- Required
    • Provides a user-friendly graphical representation of the intent of the action
    • Is required to be a 256x256 pixel PNG image
    • Must include the SHA-256 hash. Contracts containing an icon without hashes will be rejected.
    • This icon may be displayed alongside the Ricardian contract

Other Metadata Fields

User-defined metadata fields are permissible with one exception. The eosio field name is reserved for future use. Contracts containing that field will be rejected.

User-defined metadata fields may contain variables, which will be replaced during contract rendering.

Other Requirements and Considerations

Specification Versioning

The specification version follows a semantic versioning (semver) inspired scheme. This determines the compatibility that may be expected between versions. Versions are specified in the form of MAJOR.MINOR.PATCH where each element is an integer. Interpretation of these elements is as follows:

MAJOR

  • Differences of MAJOR values imply NO guarantees of compatibility between versions.
  • This will indicate a change in the specification that cannot be forward compatible. For example, adding a new REQUIRED field to the metadata.

MINOR

  • Versions having the same MAJOR version but different MINOR versions must be forward compatible. Processors of a given MAJOR.MINOR version MUST be able to successfully process contracts having the same MAJOR version and the SAME OR LOWER MINOR version.
  • Processor ARE NOT required to be able to handle contracts written to a greater MINOR version than designed for.
  • This will indicate a change in the specification that is forward compatible. For example, making a previously required field optional.

PATCH

  • Versions differing only in the PATCH version MUST be processable by any processor with the same MAJOR.MINOR version.
  • This will indicate changes in the specification that have no tangible effect on processing. For example, a textual change to the specification intended for human readability, spelling corrections, etc.

Variables

All variables used within a contract must have a value or the contract will be rejected. Variable values may be supplied in the transaction, in the contract action, or in the Ricardian clause on the ABI. In addition, the Ricardian Template Toolkit will supply variables about the transaction.

The default scope for variables is the current action's data object. The eosio.token::transfer action, for example, has from, to, quantity and memo properties. Those variables may be referenced directly: I am sending {{quantity}} tokens from {{from}} to {{to}}..

The Ricardian Template Toolkit will supply the following variables, which allow the contract to refer to other parts of the transaction:

  • $transaction – Provides access to transaction-level data like expiration or delay_sec. E.g., ...with a delay of {{$transaction.delay_sec}} seconds.
  • $action – Provides access to variables within the current action. E.g., ...using the {{$action.name}} contract on the {{$action.account}} account.
  • $clauses.clause_id – Provides access to data in the ricardian_clauses on the ABI. E.g., Section 2:\n\n{{$clauses.standard_clause}}
  • Items in an array may be accessed by index. E.g., Accessing data in another action – {{$transaction.actions.[2].data.from}}
  • $index – A pseudo-field giving you the index of the current item in the array you're within. E.g., {{$action.$index}}

Variables may include a reference to other variables. A maximum number of three variable interpolation passes will be made. If there are still unresolved variables after the third pass, the contract will be considered invalid and an error will be returned by the user agent.

For styling purposes, by default interpolated variables in the output will be wrapped in <div /> tags, all of which will have the class variable and one additional contextual class name:

  • Values coming from the default context (the current action's data values) will be given the data class (e.g., <div class="variable data">value</div>)
  • Transaction values will be given the transaction class (e.g., <div class="variable transaction">value</div>)
  • Action values will be given the action class (e.g., <div class="variable action">value</div>)
  • Clause values will be given the clauses class (e.g., <div class="variable clauses">value</div>)

In cases where this default variable wrapping can cause problems (e.g. a variable containing a URL that becomes the value of an HREF attribute) there are additional Handlebars helpers to override the default behavior.

  • To prevent an individual variable from being wrapped, use the nowrap helper.

    For example, to create a link with unwrapped individual variables:

    [{{nowrap link.text}}]({{nowrap link.url}})

  • To wrap a larger block, perhaps because it contains a link for an unwrapped variable, use the {{#wrap}}...{{/wrap}} pair around the block to highlight.

    For example, to wrap the entire link from above:

    {{#wrap}}[{{nowrap link.text}}]({{nowrap link.url}}){{/wrap}}

Handlebars Helpers

In addition to the standard helpers which are part of Handlebars, there are a number of additional helpers defined to assist with Ricardian contract specific issues.

Since v0.0

  • wrap - Takes no parameters. Block level helper to wrap the contents with <div> tags for highlighting. See Variables section above for more details.

  • nowrap - Takes a variable. Indicates that the specified variable should not be wrapped with <div> tags. See Variables section above for more details.

  • symbol_to_symbol_code - Given a variable containing a 'symbol' string, extract and return only the symbol code.

    Example:

    Given:
    symbol = '4,EOS'
    
    {{ symbol_to_symbol_code symbol }} --> 'EOS'.
    
  • asset_to_symbol_code - Given a variable containing an 'asset' string, extract and return only the symbol code.

    Example:

    Given:
    asset = '2.001 EOS'
    
    {{ asset_to_symbol_code asset }} --> 'EOS'.
    

Since v0.1

  • amount_from_asset - Given a variable containing an asset, extract and return the amount.

    Example:

    Given:
    asset = '2.001 EOS'
    
    {{ amount_from_asset asset }} --> '2.001'.
    

Since v0.2

  • to_json - Takes the given variable and renders it as a preformatted JSON string. Note that the resulting string is also surrounded by <pre><code> tags as well. This is intended as a debugging aid.

    Example:

    {{to_json nameObj}}
    
    <pre><code>
    {
      "firstname": "John",
      "lastname": "Doe"
    }
    </pre></code>
    
  • if_has_value - A block level helper which checks the given variable and if it is defined AND not null then renders the content. If the variable is undefined OR null render nothing or the contents of the {{ else }} clause if specified.

    Example:

    {{#if_has_value myVar}}
      Render if myVar has a non-null value
    {{/if_has_value}}
    
    Or
    
    {{#if_has_value myVar}}
      Render if myVar has a non-null value
    {{ else }}
      Render if myVar is undefined or null
    {{/if_has_value}}
    

HTML in Variables

By default, any {{variables}} that contain HTML will have that HTML escaped. This may not be the desired outcome, as the ricardian_clauses may have HTML that the author wants rendered rather than escaped.

To accommodate this, {{{variables}}} wrapped in triple brackets will have HTML escaping disabled. The rendered HTML will be sanitized to reduce the risk of malicious scripts.

Metadata Values Beginning With a Variable or Other Special Characters

Metadata values beginning with special characters, such as a variable bracket ({), may not be parsed properly by some engines. Ricardian metadata is YAML, and YAML values beginning with special characters are not valid. To get around this, wrap any metadata values beginning with special characters in single quotes.

Example Template

The example below shows the metadata in YAML format.

---
spec_version: 0.0.0
title: Create Post
summary: Create a blog post "{{title}}" by {{author}} tagged as "{{tag}}"
icon: https://app.com/create-post.png#00506E08A55BCF269FE67F202BBC08CFF55F9E3C7CD4459ECB90205BF3C3B562
---
I, {{author}}, author of the blog post "{{title}}", certify that I am the original author of the contents of this blog post and have attributed all external sources appropriately.

{{$clauses.legalese}}

Example ABI

"actions": [
  {
    "name": "createpost",
    "type": "createpost",
    "ricardian_contract": "---\ntitle: Create Post\nsummary: Create a blog post \"{{title}}\" by {{author}} tagged as \"{{tag}}\"\nicon: https://app.com/create-post.png#00506E08A55BCF269FE67F202BBC08CFF55F9E3C7CD4459ECB90205BF3C3B562\n---\nI, {{author}}, author of the blog post \"{{title}}\", certify that I am the original author of the contents of this blog post and have attributed all external sources appropriately.\n\n{{$clauses.legalese}}"
  }
],

...

"ricardian_clauses": [
  {
    "id": "legalese",
    "body": "WARRANTY. The invoker of the contract action shall uphold its Obligations under this Contract in a timely and workmanlike manner, using knowledge and recommendations for performing the services which meet generally acceptable standards set forth by EOS.IO Blockchain Block Producers."
  }
]

Contributing

Contributing Guide

Code of Conduct

License

MIT

Important

See LICENSE for copyright and license terms. Block.one makes its contribution on a voluntary basis as a member of the EOSIO community and is not responsible for ensuring the overall performance of the software or any related applications. We make no representation, warranty, guarantee or undertaking in respect of the software or any related documentation, whether expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall we be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or documentation or the use or other dealings in the software or documentation. Any test results or performance figures are indicative and will not reflect performance under all conditions. Any reference to any third party or third-party product, service or other resource is not an endorsement or recommendation by Block.one. We are not responsible, and disclaim any and all responsibility and liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information here may be out of date or inaccurate. Any person using or offering this software in connection with providing software, goods or services to third parties shall advise such third parties of these license terms, disclaimers and exclusions of liability. Block.one, EOSIO, EOSIO Labs, EOS, the heptahedron and associated logos are trademarks of Block.one.

Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with this software.