Fixed fee & un-splittable cents
Last updated: May 10, 2024
A splitted transaction is created, starting with a fixed amount of $0,07 to @payment_provider followed by a percentage to the same @payment_provider, then a percentage to @franchise_fee and remaining to @store.
send $value (
source = @world
destination = {
7/1999 to @payment_provider
0.6% to @payment_provider
0.5% to @franchise_fee
remaining to @store
}
Problem: in the end, a fixed fee amount of 8 cents is sent instead of 7 expected
it’s essentially due to two un-splittable cents, and the multi-pass resolution operated by the send statement. This mechanism is made to avoid introducing or losing cents in allocations (it’s essentially an implementation of the monetary allocation pattern).
First pass:
$7/1999 * 1999 = 7$ are allocated to
@payment_provider$0.6/100 * 1999 = 11.994 = 11$ are allocated to
@payment_provider(the machine recognizes that 0.994 do not make for a full AUD/2 and cannot allocate it to the account here — it keeps it on the side for a second pass)$0.5/100 * 1999 = 9.995 = 9$ are allocated to
@franchise_fee(same mechanism)$1999 - 7 - 11 - 9 - ceil(0.994+0.995) = 1970$ (the machine doesn’t attribute the amounts fragments from above at this stage — it removes them from the “remaining” value)
Second pass:
The machine recognizes that it has distributed 1999 - ceil(0.994+0.995) = 1997 out of the original 1999 of the send and hence has a remaining 2 of AUD/2 to distribute
It distributes them as evenly as possible, from top to bottom
First position
@payment_providergets 1 more AUD/2, topping this posting value from 7 to 8. Then at the second position,@payment_provideragain, gets 1 more AUD/2, topping this posting value from 11 to 12.
✅ Solution: to deal with this unexpected addition on fixed fee, we can move down the fixed-fee statement. This will move our percentage computations upstack and make them first receivers of the cents fragments. Knowing that no percentage can yield more than 1 cent fragment and that we only have two real percentage computations here with the potential for fragments, we can know that no additional extra cent will reach the @payment_provider on third destination line
send [AUD/2 1999] (
source = @world
destination = @sales:1234
)
send [AUD/2 *] (
source = @sales:1234
destination = {
0.6% to @payment_provider
0.5% to @franchise_fee
7/1999 to @payment_provider
remaining to @store
}
)