Skip to content
CommonLayer
Documentation menu
On this page

ADR-0014: Money is i64 minor units plus an ISO 4217 code

Status: Accepted (plan decision D14). Implemented in crates/commonlayer-core/src/money.rs.

Context

Floating-point arithmetic cannot represent most decimal amounts exactly; rounding differences in splits (for example a $500 target split 40/30/10/20 percent, or a slot prorated by day) must never create or destroy money.

Decision

  • Money { amount_minor: i64, currency: Currency }. All arithmetic is checked (checked_add, checked_sub, checked_mul) and returns an error on overflow.
  • Splitting uses Money::allocate(weights) with the largest-remainder method, so the parts always sum exactly to the whole (property-tested).
  • A project treasury has exactly one currency. There is no implicit conversion: a contribution in another currency is rejected with funding.currency_mismatch.
  • #![deny(clippy::float_arithmetic)] holds in commonlayer-funding and in the money module. In the database, money is <name>_minor bigint plus currency char(3).

Consequences

  • Currency conversion is out of scope.
  • The currency table is a curated list of 32 ISO codes with their minor-unit exponents (WP-01); adding one is a code change.
  • The API represents amounts as {"amount_minor": 50000, "currency": "USD"} or as *_minor fields next to a currency.