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 incommonlayer-fundingand in the money module. In the database, money is<name>_minor bigintpluscurrency 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*_minorfields next to a currency.