FA-61846 / Currency rounding and FX conversion / Open access
A padded lower-case currency code is treated as unknown · case 01
Valid amounts tagged ' usd' are rejected as unknown currencies.
ROOT CAUSE
The currency code is used verbatim instead of being trimmed and upper-cased before lookup.
THE FAILURE
The currency code is used verbatim instead of being trimmed and upper-cased before lookup.
Unsuccessful approach: Upper-casing without trimming still rejects codes that arrive with surrounding spaces.
Case contract
solve(amount, ccy): amount is an exact decimal string, ccy an ISO-like code that is trimmed and upper-cased. Minor-unit exponents: USD 2, EUR 2, JPY 0, KRW 0, KWD 3, BHD 3, CLF 4. Round the exact decimal half-even at the currency exponent and return a plain string with exactly that many fraction digits; a zero result is unsigned. Unknown codes return 'ERR:unknown-currency'.
Why this case matters
Currency amounts must be rounded at the right stage and in the right unit, or ledgers, quotes and settlements drift by minor units.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN
N = 1
observations = []
def solve(amount, ccy):
exps = {'USD': 2, 'EUR': 2, 'JPY': 0, 'KRW': 0, 'KWD': 3, 'BHD': 3, 'CLF': 4}
code = ccy
if code not in exps: return 'ERR:unknown-currency'
e = exps[code]
x = Decimal(amount)
q = x.quantize(Decimal(1).scaleb(-e), rounding=ROUND_HALF_EVEN)
if q == 0: q = abs(q)
return format(q, 'f')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression code-normalization 1', ('1.005', ' usd'), '1.00'),
('regression code-normalization 2', ('3', 'Jpy '), '3'), ('control: cents tie to even', ('2.665', 'USD'), '2.66'),
('control: yen tie', ('1235.5', 'JPY'), '1236'), ('control: dinar three places', ('10.0005', 'KWD'), '10.000'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346')],
[('regression code-normalization 1', ('12.345', ' eur '), '12.34'),
('regression code-normalization 2', ('-2562.29293', 'usd'), '-2562.29'),
('partial repair guard 2', ('47295.38', ' jpy'), '47295'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346'),
('control: negative small', ('-0.004', 'USD'), '0.00'), ('control: integer input', ('7', 'BHD'), '7.000'),
('control: unknown code', ('1.00', 'ABC'), 'ERR:unknown-currency')],
[('regression code-normalization 1', ('47295.38', ' jpy'), '47295'),
('regression code-normalization 2', ('35094.719', 'usd'), '35094.72'),
('partial repair guard 1', ('10645.65286', 'Kwd '), '10645.653'),
('partial repair guard 2', ('1600.045697', ' jpy'), '1600'), ('control: integer input', ('7', 'BHD'), '7.000'),
('control: unknown code', ('1.00', 'ABC'), 'ERR:unknown-currency'),
('control: large amount', ('123456789.125', 'USD'), '123456789.12'),
('control: negative tie', ('-2.5', 'KRW'), '-2')],
[('regression code-normalization 1', ('10645.65286', 'Kwd '), '10645.653'),
('regression code-normalization 2', ('1600.045697', ' jpy'), '1600'),
('partial repair guard 1', ('16193.1040', 'Kwd '), '16193.104'),
('partial repair guard 2', ('32233.55636', 'Kwd '), '32233.556'), ('control: negative tie', ('-2.5', 'KRW'), '-2'),
('control: cents tie to even', ('2.665', 'USD'), '2.66'), ('control: yen tie', ('1235.5', 'JPY'), '1236'),
('control: dinar three places', ('10.0005', 'KWD'), '10.000')],
[('regression code-normalization 1', ('16193.1040', 'Kwd '), '16193.104'),
('regression code-normalization 2', ('32233.55636', 'Kwd '), '32233.556'),
('partial repair guard 1', ('5555.23', ' jpy'), '5555'), ('partial repair guard 2', ('4726.8350', ' jpy'), '4727'),
('control: dinar three places', ('10.0005', 'KWD'), '10.000'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346'),
('control: lowercase code', ('12.345', ' eur '), '12.34'), ('control: negative small', ('-0.004', 'USD'), '0.00')]]
for label, args, expected in cases[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression code-normalization 1 | ERR:unknown-currency | 1.00 | Failed |
| regression code-normalization 2 | ERR:unknown-currency | 3 | Failed |
| control: cents tie to even | 2.66 | 2.66 | Passed |
| control: yen tie | 1236 | 1236 | Passed |
| control: dinar three places | 10.000 | 10.000 | Passed |
| control: unit of account four places | 1.2346 | 1.2346 | Passed |
SHA-256 / 294a4940a84f363e4290c9bb85bf9915047fe5e2bfaa4057568803cc4fcde192
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN
N = 1
observations = []
def solve(amount, ccy):
exps = {'USD': 2, 'EUR': 2, 'JPY': 0, 'KRW': 0, 'KWD': 3, 'BHD': 3, 'CLF': 4}
code = ccy.upper()
if code not in exps: return 'ERR:unknown-currency'
e = exps[code]
x = Decimal(amount)
q = x.quantize(Decimal(1).scaleb(-e), rounding=ROUND_HALF_EVEN)
if q == 0: q = abs(q)
return format(q, 'f')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression code-normalization 1', ('1.005', ' usd'), '1.00'),
('regression code-normalization 2', ('3', 'Jpy '), '3'), ('control: cents tie to even', ('2.665', 'USD'), '2.66'),
('control: yen tie', ('1235.5', 'JPY'), '1236'), ('control: dinar three places', ('10.0005', 'KWD'), '10.000'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346')],
[('regression code-normalization 1', ('12.345', ' eur '), '12.34'),
('regression code-normalization 2', ('-2562.29293', 'usd'), '-2562.29'),
('partial repair guard 2', ('47295.38', ' jpy'), '47295'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346'),
('control: negative small', ('-0.004', 'USD'), '0.00'), ('control: integer input', ('7', 'BHD'), '7.000'),
('control: unknown code', ('1.00', 'ABC'), 'ERR:unknown-currency')],
[('regression code-normalization 1', ('47295.38', ' jpy'), '47295'),
('regression code-normalization 2', ('35094.719', 'usd'), '35094.72'),
('partial repair guard 1', ('10645.65286', 'Kwd '), '10645.653'),
('partial repair guard 2', ('1600.045697', ' jpy'), '1600'), ('control: integer input', ('7', 'BHD'), '7.000'),
('control: unknown code', ('1.00', 'ABC'), 'ERR:unknown-currency'),
('control: large amount', ('123456789.125', 'USD'), '123456789.12'),
('control: negative tie', ('-2.5', 'KRW'), '-2')],
[('regression code-normalization 1', ('10645.65286', 'Kwd '), '10645.653'),
('regression code-normalization 2', ('1600.045697', ' jpy'), '1600'),
('partial repair guard 1', ('16193.1040', 'Kwd '), '16193.104'),
('partial repair guard 2', ('32233.55636', 'Kwd '), '32233.556'), ('control: negative tie', ('-2.5', 'KRW'), '-2'),
('control: cents tie to even', ('2.665', 'USD'), '2.66'), ('control: yen tie', ('1235.5', 'JPY'), '1236'),
('control: dinar three places', ('10.0005', 'KWD'), '10.000')],
[('regression code-normalization 1', ('16193.1040', 'Kwd '), '16193.104'),
('regression code-normalization 2', ('32233.55636', 'Kwd '), '32233.556'),
('partial repair guard 1', ('5555.23', ' jpy'), '5555'), ('partial repair guard 2', ('4726.8350', ' jpy'), '4727'),
('control: dinar three places', ('10.0005', 'KWD'), '10.000'),
('control: unit of account four places', ('1.23456', 'CLF'), '1.2346'),
('control: lowercase code', ('12.345', ' eur '), '12.34'), ('control: negative small', ('-0.004', 'USD'), '0.00')]]
for label, args, expected in cases[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression code-normalization 1 | ERR:unknown-currency | 1.00 | Failed |
| regression code-normalization 2 | ERR:unknown-currency | 3 | Failed |
| control: cents tie to even | 2.66 | 2.66 | Passed |
| control: yen tie | 1236 | 1236 | Passed |
| control: dinar three places | 10.000 | 10.000 | Passed |
| control: unit of account four places | 1.2346 | 1.2346 | Passed |
SHA-256 / fec17b82cc490641e6f51271e5924162c6e8fa8a0918f3711c529d34cce8a596
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 6 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
A deterministic, bounded teaching model with a stipulated toy contract; it makes no claim of conformance to any real regulation, standard, or institution's rules. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:46:59.048355+00:00.
Case digest / e1c71823090d68ec5e07f86b345f6051aea05ec0a2f02503e777ae6780557aa1