Repository: liberapay/liberapay.com

Issue:
Currency exchange rate between EUR and USD are mixed up
If I give euros to an account using dollar as main currency, the currency rate gets mixed up somewhere.
For instance if I give 5€, on the creator's page it only displays 4.05$ instead of 6.18$.

Current exchange rate:
* 5 EUR to USD: 6.18$
* 5 USD to EUR: 4.05€


Discussion:
I already knew about this bug, but thanks for creating an issue. Fixing this is next on my list.

Resolving patch:
diff --git a/liberapay/models/_mixin_team.py b/liberapay/models/_mixin_team.py
--- a/liberapay/models/_mixin_team.py
+++ b/liberapay/models/_mixin_team.py
@@ -118,8 +118,7 @@ def set_take_for(self, member, take, recorder, check_max=True, cursor=None):
             if cur_take is None:
                 return None
 
-        if not isinstance(take, (None.__class__, Money)):
-            take = Money(take, self.main_currency)  # TODO drop this
+        assert isinstance(take, (None.__class__, Money))
 
         with self.db.get_cursor(cursor) as cursor:
             # Lock to avoid race conditions


Test patch:
diff --git a/tests/py/test_callbacks.py b/tests/py/test_callbacks.py
--- a/tests/py/test_callbacks.py
+++ b/tests/py/test_callbacks.py
@@ -1,7 +1,5 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
-from decimal import Decimal as D
-
 from mock import patch
 
 from mangopay.resources import BankWirePayOut, BankWirePayIn, Dispute, PayIn, Refund
@@ -38,11 +36,11 @@ def callback(self, qs, **kw):
     @patch('mangopay.resources.SettlementTransfer.save', autospec=True)
     def test_dispute_callback_lost(self, save, get_payin, get_dispute):
         self.make_participant(
-            'LiberapayOrg', kind='organization', balance=D('100.00'),
+            'LiberapayOrg', kind='organization', balance=EUR('100.00'),
             mangopay_user_id='0', mangopay_wallet_id='0',
         )
         save.side_effect = fake_transfer
-        e_id = self.make_exchange('mango-cc', D('16'), D('1'), self.janet)
+        e_id = self.make_exchange('mango-cc', EUR('16'), EUR('1'), self.janet)
         dispute = Dispute()
         dispute.Id = '-1'
         dispute.CreationDate = utcnow()
@@ -56,10 +54,10 @@ def test_dispute_callback_lost(self, save, get_payin, get_dispute):
         self.janet.set_tip_to(self.homer, EUR('3.68'))
         Payday.start().run()
         # Withdraw some of the money
-        self.make_exchange('mango-ba', D('-2.68'), 0, self.homer)
+        self.make_exchange('mango-ba', EUR('-2.68'), 0, self.homer)
         # Add a bit of money that will remain undisputed, to test bundle swapping
-        self.make_exchange('mango-cc', D('0.32'), 0, self.janet)
-        self.make_exchange('mango-cc', D('0.55'), 0, self.homer)
+        self.make_exchange('mango-cc', EUR('0.32'), 0, self.janet)
+        self.make_exchange('mango-cc', EUR('0.55'), 0, self.homer)
         # Call back
         self.db.self_check()
         for status in ('CREATED', 'CLOSED'):
@@ -73,11 +71,11 @@ def test_dispute_callback_lost(self, save, get_payin, get_dispute):
         # Check final state
         balances = dict(self.db.all("SELECT username, balance FROM participants"))
         assert balances == {
-            '_chargebacks_': D('16.00'),
+            '_chargebacks_': EUR('16.00'),
             'david': 0,
             'homer': 0,
             'janet': 0,
-            'LiberapayOrg': D('98.19'),
+            'LiberapayOrg': EUR('98.19'),
         }
         debts = dict(((r[0], r[1]), r[2]) for r in self.db.all("""
             SELECT p_debtor.username AS debtor, p_creditor.username AS creditor, sum(d.amount)
@@ -88,9 +86,9 @@ def test_dispute_callback_lost(self, save, get_payin, get_dispute):
           GROUP BY p_debtor.username, p_creditor.username
         """))
         assert debts == {
-            ('janet', 'LiberapayOrg'): D('1.00'),
-            ('janet', 'homer'): D('3.36'),
-            ('homer', 'LiberapayOrg'): D('1.81'),
+            ('janet', 'LiberapayOrg'): EUR('1.00'),
+            ('janet', 'homer'): EUR('3.36'),
+            ('homer', 'LiberapayOrg'): EUR('1.81'),
         }
 
     @patch('mangopay.resources.Dispute.get')
@@ -99,7 +97,7 @@ def test_dispute_callback_lost(self, save, get_payin, get_dispute):
     def test_dispute_callback_won(self, save, get_payin, get_dispute):
         self.make_participant('LiberapayOrg', kind='organization')
         save.side_effect = fake_transfer
-        e_id = self.make_exchange('mango-cc', D('16'), D('1'), self.janet)
+        e_id = self.make_exchange('mango-cc', EUR('16'), EUR('1'), self.janet)
         dispute = Dispute()
         dispute.Id = '-1'
         dispute.CreationDate = utcnow()
@@ -113,9 +111,9 @@ def test_dispute_callback_won(self, save, get_payin, get_dispute):
         self.janet.set_tip_to(self.homer, EUR('3.68'))
         Payday.start().run()
         # Withdraw some of the money
-        self.make_exchange('mango-ba', D('-2.68'), 0, self.homer)
+        self.make_exchange('mango-ba', EUR('-2.68'), 0, self.homer)
         # Add money that will remain undisputed, to test bundle swapping
-        self.make_exchange('mango-cc', D('2.69'), 0, self.janet)
+        self.make_exchange('mango-cc', EUR('2.69'), 0, self.janet)
         # Call back
         self.db.self_check()
         for status in ('CREATED', 'CLOSED'):
@@ -134,8 +132,8 @@ def test_dispute_callback_won(self, save, get_payin, get_dispute):
         balances = dict(self.db.all("SELECT username, balance FROM participants"))
         assert balances == {
             'david': 0,
-            'homer': D('1.00'),
-            'janet': D('15.01'),
+            'homer': EUR('1.00'),
+            'janet': EUR('15.01'),
             'LiberapayOrg': 0,
         }
 
@@ -297,11 +295,11 @@ def test_payin_bank_wire_callback_unexpected(self, Get):
             Get.return_value = payin
             r = self.callback(qs)
             assert r.code == 200, r.text
-            amount = D(242 - fee) / D(100)
+            amount = EUR(242 - fee) / 100
             e = self.db.one("SELECT * FROM exchanges ORDER BY timestamp DESC lIMIT 1")
             assert e.status == status
             assert e.amount == amount
-            assert e.fee == D(fee) / D(100)
+            assert e.fee == EUR(fee) / 100
             homer = homer.refetch()
             if status == 'succeeded':
                 assert homer.balance == amount
@@ -348,9 +346,9 @@ def _test_payin_bank_wire_callback_amount_mismatch(self, Get, fee):
         r = self.callback(qs)
         assert r.code == 200, r.text
         e = self.db.one("SELECT * FROM exchanges WHERE id = %s", (e_id,))
-        assert e.amount == D(payin.CreditedFunds.Amount) / D(100)
-        assert e.fee == D(fee) / D(100)
-        assert e.vat == D('0.01')
+        assert e.amount == payin.CreditedFunds / 100
+        assert e.fee == EUR(fee) / 100
+        assert e.vat == EUR('0.01')
         assert e.status == 'succeeded'
         homer = homer.refetch()
         assert homer.balance == e.amount
diff --git a/tests/py/test_charts_json.py b/tests/py/test_charts_json.py
--- a/tests/py/test_charts_json.py
+++ b/tests/py/test_charts_json.py
@@ -123,8 +123,8 @@ def test_never_received_gives_empty_array(self):
 
     def test_charts_work_for_teams(self):
         team = self.make_participant('team', kind='group')
-        team.set_take_for(self.bob, 0.1, team)
-        team.set_take_for(self.carl, 1, team)
+        team.set_take_for(self.bob, EUR('0.10'), team)
+        team.set_take_for(self.carl, EUR('1.00'), team)
         self.alice.set_tip_to(team, EUR('0.30'))
         self.bob.set_tip_to(team, EUR('0.59'))
 
diff --git a/tests/py/test_close.py b/tests/py/test_close.py
--- a/tests/py/test_close.py
+++ b/tests/py/test_close.py
@@ -1,7 +1,6 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 from datetime import date
-from decimal import Decimal as D
 
 import pytest
 
@@ -18,7 +17,7 @@ class TestClosing(FakeTransfersHarness):
 
     def test_close_closes(self):
         team = self.make_participant('team', kind='group')
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
 
@@ -36,7 +35,7 @@ def test_close_closes(self):
         assert len(team.get_current_takes()) == 1
 
     def test_close_raises_for_unknown_disbursement_strategy(self):
-        alice = self.make_participant('alice', balance=D('0.00'))
+        alice = self.make_participant('alice', balance=EUR('0.00'))
         with pytest.raises(alice.UnknownDisbursementStrategy):
             alice.close('cheese')
 
@@ -53,7 +52,7 @@ def test_close_page_is_not_available_during_payday(self):
         assert 'Try Again Later' in body
 
     def test_can_post_to_close_page(self):
-        alice = self.make_participant('alice', balance=7)
+        alice = self.make_participant('alice', balance=EUR(7))
         bob = self.make_participant('bob')
         alice.set_tip_to(bob, EUR('10.00'))
 
@@ -74,19 +73,19 @@ def test_cant_post_to_close_page_during_payday(self):
     # dbafg - distribute_balance_as_final_gift
 
     def test_dbafg_distributes_balance_as_final_gift(self):
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
         alice.set_tip_to(bob, EUR('3.00'))
         alice.set_tip_to(carl, EUR('2.00'))
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
-        assert Participant.from_username('bob').balance == D('6.00')
-        assert Participant.from_username('carl').balance == D('4.00')
-        assert Participant.from_username('alice').balance == D('0.00')
+        assert Participant.from_username('bob').balance == EUR('6.00')
+        assert Participant.from_username('carl').balance == EUR('4.00')
+        assert Participant.from_username('alice').balance == EUR('0.00')
 
     def test_dbafg_needs_claimed_tips(self):
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_stub()
         carl = self.make_stub()
         alice.set_tip_to(bob, EUR('3.00'))
@@ -94,24 +93,24 @@ def test_dbafg_needs_claimed_tips(self):
         with self.db.get_cursor() as cursor:
             with pytest.raises(alice.NoOneToGiveFinalGiftTo):
                 alice.distribute_balance_as_final_gift(cursor)
-        assert Participant.from_id(bob.id).balance == D('0.00')
-        assert Participant.from_id(carl.id).balance == D('0.00')
-        assert Participant.from_id(alice.id).balance == D('10.00')
+        assert Participant.from_id(bob.id).balance == EUR('0.00')
+        assert Participant.from_id(carl.id).balance == EUR('0.00')
+        assert Participant.from_id(alice.id).balance == EUR('10.00')
 
     def test_dbafg_gives_all_to_claimed(self):
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_participant('bob')
         carl = self.make_stub()
         alice.set_tip_to(bob, EUR('3.00'))
         alice.set_tip_to(carl, EUR('2.00'))
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
-        assert Participant.from_id(bob.id).balance == D('10.00')
-        assert Participant.from_id(carl.id).balance == D('0.00')
-        assert Participant.from_id(alice.id).balance == D('0.00')
+        assert Participant.from_id(bob.id).balance == EUR('10.00')
+        assert Participant.from_id(carl.id).balance == EUR('0.00')
+        assert Participant.from_id(alice.id).balance == EUR('0.00')
 
     def test_dbafg_skips_zero_tips(self):
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
         alice.set_tip_to(bob, EUR('0.00'))
@@ -119,24 +118,24 @@ def test_dbafg_skips_zero_tips(self):
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
         assert self.db.one("SELECT count(*) FROM tips WHERE tippee=%s", (bob.id,)) == 1
-        assert Participant.from_username('bob').balance == D('0.00')
-        assert Participant.from_username('carl').balance == D('10.00')
-        assert Participant.from_username('alice').balance == D('0.00')
+        assert Participant.from_username('bob').balance == EUR('0.00')
+        assert Participant.from_username('carl').balance == EUR('10.00')
+        assert Participant.from_username('alice').balance == EUR('0.00')
 
     def test_dbafg_favors_highest_tippee_in_rounding_errors(self):
-        alice = self.make_participant('alice', balance=D('10.00'))
+        alice = self.make_participant('alice', balance=EUR('10.00'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
         alice.set_tip_to(bob, EUR('3.00'))
         alice.set_tip_to(carl, EUR('6.00'))
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
-        assert Participant.from_username('bob').balance == D('3.33')
-        assert Participant.from_username('carl').balance == D('6.67')
-        assert Participant.from_username('alice').balance == D('0.00')
+        assert Participant.from_username('bob').balance == EUR('3.33')
+        assert Participant.from_username('carl').balance == EUR('6.67')
+        assert Participant.from_username('alice').balance == EUR('0.00')
 
     def test_dbafg_with_zero_balance_is_a_noop(self):
-        alice = self.make_participant('alice', balance=D('0.00'))
+        alice = self.make_participant('alice', balance=EUR('0.00'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
         alice.set_tip_to(bob, EUR('3.00'))
@@ -144,23 +143,23 @@ def test_dbafg_with_zero_balance_is_a_noop(self):
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
         assert self.db.one("SELECT count(*) FROM tips") == 2
-        assert Participant.from_username('bob').balance == D('0.00')
-        assert Participant.from_username('carl').balance == D('0.00')
-        assert Participant.from_username('alice').balance == D('0.00')
+        assert Participant.from_username('bob').balance == EUR('0.00')
+        assert Participant.from_username('carl').balance == EUR('0.00')
+        assert Participant.from_username('alice').balance == EUR('0.00')
 
     def test_dbafg_distributes_to_team(self):
         team = self.make_participant('team', kind='group')
-        alice = self.make_participant('alice', balance=D('0.01'))
+        alice = self.make_participant('alice', balance=EUR('0.01'))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl')
         alice.set_tip_to(team, EUR('3.00'))
-        team.set_take_for(alice, 1, team)
-        team.set_take_for(bob, 1, team)
-        team.set_take_for(carl, D('0.01'), team)
+        team.set_take_for(alice, EUR('1.00'), team)
+        team.set_take_for(bob, EUR('1.00'), team)
+        team.set_take_for(carl, EUR('0.01'), team)
         with self.db.get_cursor() as cursor:
             alice.distribute_balance_as_final_gift(cursor)
         assert alice.balance == 0
-        assert bob.refetch().balance == D('0.01')
+        assert bob.refetch().balance == EUR('0.01')
         assert carl.refetch().balance == 0
 
 
diff --git a/tests/py/test_communities.py b/tests/py/test_communities.py
--- a/tests/py/test_communities.py
+++ b/tests/py/test_communities.py
@@ -4,7 +4,7 @@
 
 from liberapay.exceptions import AuthRequired
 from liberapay.models.community import Community
-from liberapay.testing import Harness
+from liberapay.testing import EUR, Harness
 
 
 class Tests(Harness):
@@ -13,7 +13,7 @@ def setUp(self):
         Harness.setUp(self)
 
         # Alice joins a community.
-        self.alice = self.make_participant('alice', balance=100)
+        self.alice = self.make_participant('alice', balance=EUR(100))
         c = self.alice.create_community('C++')
         self.alice.upsert_community_membership(True, c.id)
 
diff --git a/tests/py/test_currencies.py b/tests/py/test_currencies.py
new file mode 100644
--- /dev/null
+++ b/tests/py/test_currencies.py
@@ -0,0 +1,14 @@
+from __future__ import division, print_function, unicode_literals
+
+from liberapay.testing import EUR, USD, Harness
+
+
+class TestCurrencies(Harness):
+
+    def test_convert(self):
+        original = EUR('1.00')
+        expected = USD('1.20')
+        actual = self.db.one("SELECT convert(%s, %s)", (original, expected.currency))
+        assert expected == actual
+        actual = original.convert(expected.currency)
+        assert expected == actual
diff --git a/tests/py/test_elsewhere.py b/tests/py/test_elsewhere.py
--- a/tests/py/test_elsewhere.py
+++ b/tests/py/test_elsewhere.py
@@ -1,6 +1,5 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
-from decimal import Decimal as D
 import json
 
 import mock
@@ -115,12 +114,12 @@ def test_user_pages(self, get_user_info):
     @mock.patch('liberapay.elsewhere._base.Platform.get_user_info')
     def test_user_page_shows_pledges(self, get_user_info):
         alice = self.make_elsewhere('github', 1, 'alice').participant
-        bob = self.make_participant('bob', balance=100)
-        amount = D('14.97')
-        bob.set_tip_to(alice, EUR(amount))
+        bob = self.make_participant('bob', balance=EUR(100))
+        amount = EUR('14.97')
+        bob.set_tip_to(alice, amount)
         assert alice.receiving == amount
         r = self.client.GET('/on/github/alice/')
-        assert str(amount) in r.text, r.text
+        assert str(amount.amount) in r.text, r.text
 
     @mock.patch('liberapay.elsewhere._base.Platform.get_user_info')
     def test_user_page_doesnt_fail_on_at_sign(self, get_user_info):
diff --git a/tests/py/test_goal.py b/tests/py/test_goal.py
--- a/tests/py/test_goal.py
+++ b/tests/py/test_goal.py
@@ -1,8 +1,6 @@
 from __future__ import print_function, unicode_literals
 
-from decimal import Decimal
-
-from liberapay.testing import Harness
+from liberapay.testing import EUR, Harness
 
 
 class Tests(Harness):
@@ -46,7 +44,7 @@ def test_change_goal(self):
         self.change_goal("custom", "400")
 
         actual = self.db.one("SELECT goal FROM participants")
-        assert actual == Decimal("400.00")
+        assert actual == EUR('400.00')
 
         actual = self.db.all("""
             SELECT payload
@@ -65,4 +63,4 @@ def test_team_member_can_change_team_goal(self):
             auth_as=self.alice
         )
         assert r.code == 302
-        assert team.refetch().goal == Decimal('99.99')
+        assert team.refetch().goal == EUR('99.99')
diff --git a/tests/py/test_history.py b/tests/py/test_history.py
--- a/tests/py/test_history.py
+++ b/tests/py/test_history.py
@@ -1,7 +1,6 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 from datetime import datetime
-from decimal import Decimal
 import json
 
 from liberapay.billing.payday import Payday
@@ -54,7 +53,7 @@ def test_iter_payday_events(self):
         david = self.make_participant('david')
         self.make_exchange('mango-cc', 10000, 0, david)
         david.set_tip_to(team, EUR('1.00'))
-        team.set_take_for(bob, Decimal('1.00'), team)
+        team.set_take_for(bob, EUR('1.00'), team)
         alice.set_tip_to(bob, EUR('5.00'))
 
         assert bob.balance == 0
diff --git a/tests/py/test_identity.py b/tests/py/test_identity.py
--- a/tests/py/test_identity.py
+++ b/tests/py/test_identity.py
@@ -2,11 +2,9 @@
 
 from __future__ import print_function, unicode_literals
 
-from decimal import Decimal as D
-
 from liberapay.billing.transactions import charge, create_wallet
 from liberapay.models.exchange_route import ExchangeRoute
-from liberapay.testing import Harness
+from liberapay.testing import EUR, Harness
 from liberapay.testing.mangopay import create_card
 
 
@@ -51,7 +49,7 @@ def test_identity_form(self):
         create_wallet(self.db, janeway, 'EUR')
         cr = create_card(janeway.mangopay_user_id)
         route = ExchangeRoute.insert(janeway, 'mango-cc', cr.CardId, currency='EUR')
-        charge(self.db, route, D('20.00'), 'http://127.0.0.1/')
+        charge(self.db, route, EUR('20.00'), 'http://127.0.0.1/')
 
         # Switch to a legal user
         data = dict(data2)
diff --git a/tests/py/test_pages.py b/tests/py/test_pages.py
--- a/tests/py/test_pages.py
+++ b/tests/py/test_pages.py
@@ -104,7 +104,7 @@ def test_new_participant_can_browse(self):
 
     def test_active_participant_can_browse(self):
         self.browse_setup()
-        bob = self.make_participant('bob', balance=50)
+        bob = self.make_participant('bob', balance=EUR(50))
         bob.set_tip_to(self.david, EUR('1.00'))
         self.david.set_tip_to(bob, EUR('0.50'))
         self.browse(auth_as=self.david)
diff --git a/tests/py/test_participant.py b/tests/py/test_participant.py
--- a/tests/py/test_participant.py
+++ b/tests/py/test_participant.py
@@ -1,7 +1,5 @@
 from __future__ import print_function, unicode_literals
 
-from decimal import Decimal
-
 from six.moves.http_cookies import SimpleCookie
 
 from mangopay.utils import Money
@@ -75,7 +73,7 @@ def test_do_not_take_over_zero_tips_receiving(self):
         self.db.self_check()
 
     def test_consolidated_tips_receiving(self):
-        alice = self.make_participant('alice', balance=1)
+        alice = self.make_participant('alice', balance=EUR(1))
         bob = self.make_participant('bob', elsewhere='twitter')
         carl = self.make_elsewhere('github', -1, 'carl')
         alice.set_tip_to(bob, EUR('1.00'))  # funded
@@ -260,7 +258,7 @@ def test_bad_username(self):
     # set_tip_to - stt
 
     def test_stt_sets_tip_to(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_stub()
         alice.set_tip_to(bob, EUR('1.00'))
 
@@ -268,7 +266,7 @@ def test_stt_sets_tip_to(self):
         assert actual == EUR('1.00')
 
     def test_stt_works_for_pledges(self):
-        alice = self.make_participant('alice', balance=1)
+        alice = self.make_participant('alice', balance=EUR(1))
         bob = self.make_stub()
         t = alice.set_tip_to(bob, EUR('10.00'))
         assert isinstance(t, dict)
@@ -279,7 +277,7 @@ def test_stt_works_for_pledges(self):
         assert t['first_time_tipper'] is True
 
     def test_stt_works_for_donations(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         t = alice.set_tip_to(bob, EUR('1.00'))
         assert t['amount'] == 1
@@ -288,19 +286,19 @@ def test_stt_works_for_donations(self):
         assert t['first_time_tipper'] is True
 
     def test_stt_works_for_monthly_donations(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         t = alice.set_tip_to(bob, EUR('4.33'), 'monthly')
         assert t['amount'] == 1
 
     def test_stt_works_for_yearly_donations(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         t = alice.set_tip_to(bob, EUR('104'), 'yearly')
         assert t['amount'] == 2
 
     def test_stt_returns_False_for_second_time_tipper(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         alice.set_tip_to(bob, EUR('1.00'))
         actual = alice.set_tip_to(bob, EUR('2.00'))
@@ -308,25 +306,25 @@ def test_stt_returns_False_for_second_time_tipper(self):
         assert actual['first_time_tipper'] is False
 
     def test_stt_doesnt_allow_self_tipping(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         with pytest.raises(NoSelfTipping):
             alice.set_tip_to(alice, EUR('10.00'))
 
     def test_stt_doesnt_allow_just_any_ole_amount(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         with pytest.raises(BadAmount):
             alice.set_tip_to(bob, EUR('1000.00'))
 
     def test_stt_fails_to_tip_unknown_people(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         with pytest.raises(NoTippee):
             alice.set_tip_to('bob', EUR('1.00'))
 
     # giving, npatrons and receiving
 
     def test_only_funded_tips_count(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         carl = self.make_participant('carl', last_bill_result="Fail!")
         dana = self.make_participant('dana')
@@ -336,39 +334,39 @@ def test_only_funded_tips_count(self):
         bob.set_tip_to(dana, EUR('2.00'))
         carl.set_tip_to(dana, EUR('2.08'))
 
-        assert alice.giving == Decimal('9.00')
-        assert alice.receiving == Decimal('5.00')
-        assert bob.giving == Decimal('5.00')
-        assert bob.receiving == Decimal('6.00')
-        assert carl.giving == Decimal('0.00')
-        assert carl.receiving == Decimal('0.00')
-        assert dana.receiving == Decimal('3.00')
+        assert alice.giving == EUR('9.00')
+        assert alice.receiving == EUR('5.00')
+        assert bob.giving == EUR('5.00')
+        assert bob.receiving == EUR('6.00')
+        assert carl.giving == EUR('0.00')
+        assert carl.receiving == EUR('0.00')
+        assert dana.receiving == EUR('3.00')
         assert dana.npatrons == 1
 
         funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id")
         assert funded_tips == [3, 6, 5]
 
     def test_only_latest_tip_counts(self):
-        alice = self.make_participant('alice', balance=100)
-        bob = self.make_participant('bob', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
+        bob = self.make_participant('bob', balance=EUR(100))
         carl = self.make_participant('carl')
         alice.set_tip_to(carl, EUR('12.00'))
         alice.set_tip_to(carl, EUR('3.00'))
         bob.set_tip_to(carl, EUR('2.00'))
         bob.set_tip_to(carl, EUR('0.00'))
-        assert alice.giving == Decimal('3.00')
-        assert bob.giving == Decimal('0.00')
-        assert carl.receiving == Decimal('3.00')
+        assert alice.giving == EUR('3.00')
+        assert bob.giving == EUR('0.00')
+        assert carl.receiving == EUR('3.00')
         assert carl.npatrons == 1
 
     def test_receiving_includes_taking_when_updated_from_set_tip_to(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob', taking=EUR('42.00'))
         alice.set_tip_to(bob, EUR('3.00'))
-        assert Participant.from_username('bob').receiving == bob.receiving == Decimal('45.00')
+        assert Participant.from_username('bob').receiving == bob.receiving == EUR('45.00')
 
     def test_receiving_is_zero_for_patrons(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
         alice.set_tip_to(bob, EUR('3.00'))
 
@@ -381,16 +379,16 @@ def test_receiving_is_zero_for_patrons(self):
     # pledging
 
     def test_cant_pledge_to_locked_accounts(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_stub(goal=EUR(-1))
         with self.assertRaises(UserDoesntAcceptTips):
             alice.set_tip_to(bob, EUR('3.00'))
 
     def test_pledging_isnt_giving(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_elsewhere('github', 58946, 'bob').participant
         alice.set_tip_to(bob, EUR('3.00'))
-        assert alice.giving == Decimal('0.00')
+        assert alice.giving == EUR('0.00')
 
     # get_age_in_seconds - gais
 
diff --git a/tests/py/test_payday.py b/tests/py/test_payday.py
--- a/tests/py/test_payday.py
+++ b/tests/py/test_payday.py
@@ -1,6 +1,5 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
-from decimal import Decimal as D
 import json
 
 import mock
@@ -66,16 +65,16 @@ def test_payday_moves_money(self):
         janet = Participant.from_username('janet')
         homer = Participant.from_username('homer')
 
-        assert homer.balance == D('6.00')
-        assert janet.balance == D('4.00')
+        assert homer.balance == EUR('6.00')
+        assert janet.balance == EUR('4.00')
 
         assert self.transfer_mock.call_count
 
     def test_update_cached_amounts(self):
         team = self.make_participant('team', kind='group')
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
-        carl = self.make_participant('carl', balance=1.56)
+        carl = self.make_participant('carl', balance=EUR(1.56))
         dana = self.make_participant('dana')
         emma = Participant.make_stub(username='emma')
         team2 = self.make_participant('team2', kind='group')
@@ -87,7 +86,7 @@ def test_update_cached_amounts(self):
         alice.set_tip_to(team2, EUR('0.49'))
         bob.set_tip_to(alice, EUR('5.00'))
         team.add_member(bob)
-        team.set_take_for(bob, D('1.00'), team)
+        team.set_take_for(bob, EUR('1.00'), team)
         bob.set_tip_to(dana, EUR('2.00'))  # funded by bob's take
         bob.set_tip_to(emma, EUR('7.00'))  # not funded, insufficient receiving
         carl.set_tip_to(dana, EUR('2.08'))  # not funded, insufficient balance
@@ -98,37 +97,37 @@ def check():
             carl = Participant.from_username('carl')
             dana = Participant.from_username('dana')
             emma = Participant.from_username('emma')
-            assert alice.giving == D('10.69')
-            assert alice.receiving == D('5.00')
+            assert alice.giving == EUR('10.69')
+            assert alice.receiving == EUR('5.00')
             assert alice.npatrons == 1
             assert alice.nteampatrons == 0
-            assert bob.giving == D('7.00')
-            assert bob.receiving == D('7.00')
-            assert bob.taking == D('1.00')
+            assert bob.giving == EUR('7.00')
+            assert bob.receiving == EUR('7.00')
+            assert bob.taking == EUR('1.00')
             assert bob.npatrons == 1
             assert bob.nteampatrons == 1
-            assert carl.giving == D('0.00')
-            assert carl.receiving == D('0.00')
+            assert carl.giving == EUR('0.00')
+            assert carl.receiving == EUR('0.00')
             assert carl.npatrons == 0
             assert carl.nteampatrons == 0
-            assert dana.receiving == D('5.00')
+            assert dana.receiving == EUR('5.00')
             assert dana.npatrons == 2
             assert dana.nteampatrons == 0
-            assert emma.receiving == D('0.50')
+            assert emma.receiving == EUR('0.50')
             assert emma.npatrons == 1
             assert emma.nteampatrons == 0
             funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id")
-            assert funded_tips == [3, 6, 0.5, D('1.20'), D('0.49'), 5, 2]
+            assert funded_tips == [3, 6, 0.5, EUR('1.20'), EUR('0.49'), 5, 2]
 
             team = Participant.from_username('team')
-            assert team.receiving == D('1.20')
+            assert team.receiving == EUR('1.20')
             assert team.npatrons == 1
-            assert team.leftover == D('0.20')
+            assert team.leftover == EUR('0.20')
 
             team2 = Participant.from_username('team2')
-            assert team2.receiving == D('0.49')
+            assert team2.receiving == EUR('0.49')
             assert team2.npatrons == 1
-            assert team2.leftover == D('0.49')
+            assert team2.leftover == EUR('0.49')
 
             janet = self.janet.refetch()
             assert janet.giving == 0
@@ -170,7 +169,7 @@ def check():
         check()
 
     def test_update_cached_amounts_depth(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         usernames = ('bob', 'carl', 'dana', 'emma', 'fred', 'greg')
         users = [self.make_participant(username) for username in usernames]
 
@@ -182,8 +181,8 @@ def test_update_cached_amounts_depth(self):
         def check():
             for username in reversed(usernames[1:]):
                 user = Participant.from_username(username)
-                assert user.giving == D('1.00')
-                assert user.receiving == D('1.00')
+                assert user.giving == EUR('1.00')
+                assert user.receiving == EUR('1.00')
                 assert user.npatrons == 1
             funded_tips = self.db.all("SELECT id FROM tips WHERE is_funded ORDER BY id")
             assert len(funded_tips) == 6
@@ -195,7 +194,7 @@ def check():
     @mock.patch('liberapay.billing.payday.log')
     def test_start_prepare(self, log):
         self.clear_tables()
-        self.make_participant('carl', balance=10)
+        self.make_participant('carl', balance=EUR(10))
 
         payday = Payday.start()
         ts_start = payday.ts_start
@@ -296,7 +295,7 @@ def test_transfer_tips(self):
             assert not nulls
 
     def test_transfer_tips_whole_graph(self):
-        alice = self.make_participant('alice', balance=50)
+        alice = self.make_participant('alice', balance=EUR(50))
         alice.set_tip_to(self.homer, EUR('50'))
         self.homer.set_tip_to(self.janet, EUR('20'))
         self.janet.set_tip_to(self.david, EUR('5'))
@@ -315,16 +314,16 @@ def test_transfer_tips_whole_graph(self):
     def test_transfer_takes(self):
         a_team = self.make_participant('a_team', kind='group')
         alice = self.make_participant('alice')
-        a_team.set_take_for(alice, D('1.00'), a_team)
+        a_team.set_take_for(alice, EUR('1.00'), a_team)
         bob = self.make_participant('bob')
-        a_team.set_take_for(bob, D('0.01'), a_team)
-        charlie = self.make_participant('charlie', balance=1000)
+        a_team.set_take_for(bob, EUR('0.01'), a_team)
+        charlie = self.make_participant('charlie', balance=EUR(1000))
         charlie.set_tip_to(a_team, EUR('1.01'))
 
         payday = Payday.start()
 
         # Test that payday ignores takes set after it started
-        a_team.set_take_for(alice, D('2.00'), a_team)
+        a_team.set_take_for(alice, EUR('2.00'), a_team)
 
         # Run the transfer multiple times to make sure we ignore takes that
         # have already been processed
@@ -339,11 +338,11 @@ def test_transfer_takes(self):
 
         for p in participants:
             if p.username == 'alice':
-                assert p.balance == D('1.00')
+                assert p.balance == EUR('1.00')
             elif p.username == 'bob':
-                assert p.balance == D('0.01')
+                assert p.balance == EUR('0.01')
             elif p.username == 'charlie':
-                assert p.balance == D('998.99')
+                assert p.balance == EUR('998.99')
             else:
                 assert p.balance == 0
 
@@ -351,20 +350,20 @@ def test_underfunded_team(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('1.00'), team)
+        team.set_take_for(alice, EUR('1.00'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('1.00'), team)
-        charlie = self.make_participant('charlie', balance=1000)
+        team.set_take_for(bob, EUR('1.00'), team)
+        charlie = self.make_participant('charlie', balance=EUR(1000))
         charlie.set_tip_to(team, EUR('0.26'))
 
         Payday.start().run()
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.13'),
-            'bob': D('0.13'),
-            'charlie': D('999.74'),
-            'team': D('0.00'),
+            'alice': EUR('0.13'),
+            'bob': EUR('0.13'),
+            'charlie': EUR('999.74'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -377,23 +376,23 @@ def test_wellfunded_team(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('0.79'), team)
+        team.set_take_for(alice, EUR('0.79'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('0.21'), team)
-        charlie = self.make_participant('charlie', balance=10)
+        team.set_take_for(bob, EUR('0.21'), team)
+        charlie = self.make_participant('charlie', balance=EUR(10))
         charlie.set_tip_to(team, EUR('5.00'))
-        dan = self.make_participant('dan', balance=10)
+        dan = self.make_participant('dan', balance=EUR(10))
         dan.set_tip_to(team, EUR('5.00'))
 
         Payday.start().run()
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79'),
-            'bob': D('0.21'),
-            'charlie': D('9.5'),
-            'dan': D('9.5'),
-            'team': D('0.00'),
+            'alice': EUR('0.79'),
+            'bob': EUR('0.21'),
+            'charlie': EUR('9.5'),
+            'dan': EUR('9.5'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -401,10 +400,10 @@ def test_wellfunded_team_with_early_donor(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('0.79'), team)
+        team.set_take_for(alice, EUR('0.79'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('0.21'), team)
-        charlie = self.make_participant('charlie', balance=10)
+        team.set_take_for(bob, EUR('0.21'), team)
+        charlie = self.make_participant('charlie', balance=EUR(10))
         charlie.set_tip_to(team, EUR('2.00'))
 
         print("> Step 1: three weeks of donations from charlie only")
@@ -415,17 +414,17 @@ def test_wellfunded_team_with_early_donor(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 3,
-            'bob': D('0.21') * 3,
-            'charlie': D('7.00'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 3,
+            'bob': EUR('0.21') * 3,
+            'charlie': EUR('7.00'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
         print("> Step 2: dan joins the party, charlie's donation is automatically "
               "reduced while dan catches up")
         print()
-        dan = self.make_participant('dan', balance=10)
+        dan = self.make_participant('dan', balance=EUR(10))
         dan.set_tip_to(team, EUR('2.00'))
 
         for i in range(6):
@@ -434,11 +433,11 @@ def test_wellfunded_team_with_early_donor(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 9,
-            'bob': D('0.21') * 9,
-            'charlie': D('5.50'),
-            'dan': D('5.50'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 9,
+            'bob': EUR('0.21') * 9,
+            'charlie': EUR('5.50'),
+            'dan': EUR('5.50'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -450,11 +449,11 @@ def test_wellfunded_team_with_early_donor(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 12,
-            'bob': D('0.21') * 12,
-            'charlie': D('4.00'),
-            'dan': D('4.00'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 12,
+            'bob': EUR('0.21') * 12,
+            'charlie': EUR('4.00'),
+            'dan': EUR('4.00'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -462,12 +461,12 @@ def test_wellfunded_team_with_two_early_donors(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('0.79'), team)
+        team.set_take_for(alice, EUR('0.79'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('0.21'), team)
-        charlie = self.make_participant('charlie', balance=10)
+        team.set_take_for(bob, EUR('0.21'), team)
+        charlie = self.make_participant('charlie', balance=EUR(10))
         charlie.set_tip_to(team, EUR('1.00'))
-        dan = self.make_participant('dan', balance=10)
+        dan = self.make_participant('dan', balance=EUR(10))
         dan.set_tip_to(team, EUR('3.00'))
 
         print("> Step 1: three weeks of donations from early donors")
@@ -478,18 +477,18 @@ def test_wellfunded_team_with_two_early_donors(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 3,
-            'bob': D('0.21') * 3,
-            'charlie': D('9.25'),
-            'dan': D('7.75'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 3,
+            'bob': EUR('0.21') * 3,
+            'charlie': EUR('9.25'),
+            'dan': EUR('7.75'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
         print("> Step 2: a new donor appears, the contributions of the early "
               "donors automatically decrease while the new donor catches up")
         print()
-        emma = self.make_participant('emma', balance=10)
+        emma = self.make_participant('emma', balance=EUR(10))
         emma.set_tip_to(team, EUR('1.00'))
 
         Payday.start().run(recompute_stats=0, update_cached_amounts=False)
@@ -497,12 +496,12 @@ def test_wellfunded_team_with_two_early_donors(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 4,
-            'bob': D('0.21') * 4,
-            'charlie': D('9.19'),
-            'dan': D('7.59'),
-            'emma': D('9.22'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 4,
+            'bob': EUR('0.21') * 4,
+            'charlie': EUR('9.19'),
+            'dan': EUR('7.59'),
+            'emma': EUR('9.22'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -511,12 +510,12 @@ def test_wellfunded_team_with_two_early_donors(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 5,
-            'bob': D('0.21') * 5,
-            'charlie': D('8.99'),
-            'dan': D('7.01'),
-            'emma': D('9.00'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 5,
+            'bob': EUR('0.21') * 5,
+            'charlie': EUR('8.99'),
+            'dan': EUR('7.01'),
+            'emma': EUR('9.00'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -529,12 +528,12 @@ def test_wellfunded_team_with_two_early_donors(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.79') * 7,
-            'bob': D('0.21') * 7,
-            'charlie': D('8.60'),
-            'dan': D('5.80'),
-            'emma': D('8.60'),
-            'team': D('0.00'),
+            'alice': EUR('0.79') * 7,
+            'bob': EUR('0.21') * 7,
+            'charlie': EUR('8.60'),
+            'dan': EUR('5.80'),
+            'emma': EUR('8.60'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -542,12 +541,12 @@ def test_wellfunded_team_with_two_early_donors_and_low_amounts(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('0.01'), team)
+        team.set_take_for(alice, EUR('0.01'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('0.01'), team)
-        charlie = self.make_participant('charlie', balance=10)
+        team.set_take_for(bob, EUR('0.01'), team)
+        charlie = self.make_participant('charlie', balance=EUR(10))
         charlie.set_tip_to(team, EUR('0.02'))
-        dan = self.make_participant('dan', balance=10)
+        dan = self.make_participant('dan', balance=EUR(10))
         dan.set_tip_to(team, EUR('0.02'))
 
         print("> Step 1: three weeks of donations from early donors")
@@ -558,18 +557,18 @@ def test_wellfunded_team_with_two_early_donors_and_low_amounts(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.01') * 3,
-            'bob': D('0.01') * 3,
-            'charlie': D('9.97'),
-            'dan': D('9.97'),
-            'team': D('0.00'),
+            'alice': EUR('0.01') * 3,
+            'bob': EUR('0.01') * 3,
+            'charlie': EUR('9.97'),
+            'dan': EUR('9.97'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
         print("> Step 2: a new donor appears, the contributions of the early "
               "donors automatically decrease while the new donor catches up")
         print()
-        emma = self.make_participant('emma', balance=10)
+        emma = self.make_participant('emma', balance=EUR(10))
         emma.set_tip_to(team, EUR('0.02'))
 
         for i in range(6):
@@ -578,12 +577,12 @@ def test_wellfunded_team_with_two_early_donors_and_low_amounts(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.01') * 9,
-            'bob': D('0.01') * 9,
-            'charlie': D('9.94'),
-            'dan': D('9.94'),
-            'emma': D('9.94'),
-            'team': D('0.00'),
+            'alice': EUR('0.01') * 9,
+            'bob': EUR('0.01') * 9,
+            'charlie': EUR('9.94'),
+            'dan': EUR('9.94'),
+            'emma': EUR('9.94'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -591,10 +590,10 @@ def test_wellfunded_team_with_early_donor_and_small_leftover(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
         alice = self.make_participant('alice')
-        team.set_take_for(alice, D('0.50'), team)
+        team.set_take_for(alice, EUR('0.50'), team)
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('0.50'), team)
-        charlie = self.make_participant('charlie', balance=10)
+        team.set_take_for(bob, EUR('0.50'), team)
+        charlie = self.make_participant('charlie', balance=EUR(10))
         charlie.set_tip_to(team, EUR('0.52'))
 
         print("> Step 1: three weeks of donations from early donor")
@@ -605,10 +604,10 @@ def test_wellfunded_team_with_early_donor_and_small_leftover(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.26') * 3,
-            'bob': D('0.26') * 3,
-            'charlie': D('8.44'),
-            'team': D('0.00'),
+            'alice': EUR('0.26') * 3,
+            'bob': EUR('0.26') * 3,
+            'charlie': EUR('8.44'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -616,7 +615,7 @@ def test_wellfunded_team_with_early_donor_and_small_leftover(self):
               "donor automatically decreases while the new donor catches up, "
               "but the leftover is small so the adjustments are limited")
         print()
-        dan = self.make_participant('dan', balance=10)
+        dan = self.make_participant('dan', balance=EUR(10))
         dan.set_tip_to(team, EUR('0.52'))
 
         for i in range(3):
@@ -625,31 +624,31 @@ def test_wellfunded_team_with_early_donor_and_small_leftover(self):
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.26') * 3 + D('0.50') * 3,
-            'bob': D('0.26') * 3 + D('0.50') * 3,
-            'charlie': D('7.00'),
-            'dan': D('8.44'),
-            'team': D('0.00'),
+            'alice': EUR('0.26') * 3 + EUR('0.50') * 3,
+            'bob': EUR('0.26') * 3 + EUR('0.50') * 3,
+            'charlie': EUR('7.00'),
+            'dan': EUR('8.44'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
     def test_mutual_tipping_through_teams(self):
         self.clear_tables()
         team = self.make_participant('team', kind='group')
-        alice = self.make_participant('alice', balance=8)
+        alice = self.make_participant('alice', balance=EUR(8))
         alice.set_tip_to(team, EUR('2.00'))
-        team.set_take_for(alice, D('0.25'), team)
-        bob = self.make_participant('bob', balance=10)
+        team.set_take_for(alice, EUR('0.25'), team)
+        bob = self.make_participant('bob', balance=EUR(10))
         bob.set_tip_to(team, EUR('2.00'))
-        team.set_take_for(bob, D('0.75'), team)
+        team.set_take_for(bob, EUR('0.75'), team)
 
         Payday.start().run()
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('7.75'),  # 8 - 0.50 + 0.25
-            'bob': D('10.25'),  # 10 - 0.25 + 0.50
-            'team': D('0.00'),
+            'alice': EUR('7.75'),  # 8 - 0.50 + 0.25
+            'bob': EUR('10.25'),  # 10 - 0.25 + 0.50
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -659,15 +658,15 @@ def test_unfunded_tip_to_team_doesnt_cause_NegativeBalance(self):
         alice = self.make_participant('alice')
         alice.set_tip_to(team, EUR('1.00'))  # unfunded tip
         bob = self.make_participant('bob')
-        team.set_take_for(bob, D('1.00'), team)
+        team.set_take_for(bob, EUR('1.00'), team)
 
         Payday.start().run()
 
         d = dict(self.db.all("SELECT username, balance FROM participants"))
         expected = {
-            'alice': D('0.00'),
-            'bob': D('0.00'),
-            'team': D('0.00'),
+            'alice': EUR('0.00'),
+            'bob': EUR('0.00'),
+            'team': EUR('0.00'),
         }
         assert d == expected
 
@@ -717,8 +716,8 @@ def test_it_handles_invoices_correctly(self):
         assert len(expense_transfers) == 1
         d = dict(self.db.all("SELECT username, balance FROM participants WHERE balance <> 0"))
         assert d == {
-            'org': D('9.98'),
-            'janet': D('50.02'),
+            'org': EUR('9.98'),
+            'janet': EUR('50.02'),
         }
 
     def test_payday_tries_to_settle_debts(self):
@@ -755,7 +754,7 @@ def test_it_notifies_participants(self):
         team = self.make_participant('team', kind='group', email='team@example.com')
         self.janet.set_tip_to(team, EUR('0.25'))
         team.add_member(self.david)
-        team.set_take_for(self.david, D('0.23'), team)
+        team.set_take_for(self.david, EUR('0.23'), team)
         self.client.POST('/homer/emails/notifications.json', auth_as=self.homer,
                          data={'fields': 'income', 'income': ''}, xhr=True)
         kalel = self.make_participant(
@@ -764,10 +763,10 @@ def test_it_notifies_participants(self):
         self.janet.set_tip_to(kalel, EUR('0.10'))
         Payday.start().run()
         david = self.david.refetch()
-        assert david.balance == D('4.73')
+        assert david.balance == EUR('4.73')
         janet = self.janet.refetch()
-        assert janet.balance == D('1.77')
-        assert janet.giving == D('0.25')
+        assert janet.balance == EUR('1.77')
+        assert janet.giving == EUR('0.25')
         emails = self.get_emails()
         assert len(emails) == 3
         assert emails[0]['to'][0] == 'david <%s>' % self.david.email
diff --git a/tests/py/test_payio.py b/tests/py/test_payio.py
--- a/tests/py/test_payio.py
+++ b/tests/py/test_payio.py
@@ -1,7 +1,6 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 from datetime import datetime
-from decimal import Decimal as D
 
 import mock
 from pando.utils import utc
@@ -50,13 +49,13 @@ def fail_payin(payin):
 class TestPayouts(MangopayHarness):
 
     def test_payout(self):
-        e = charge(self.db, self.janet_route, D('46.00'), 'http://localhost/')
+        e = charge(self.db, self.janet_route, EUR('46.00'), 'http://localhost/')
         assert e.status == 'succeeded', e.note
         self.janet.set_tip_to(self.homer, EUR('42.00'))
         self.janet.close('downstream')
         self.homer = self.homer.refetch()
         assert self.homer.balance == 46
-        exchange = payout(self.db, self.homer_route, D('30.00'))
+        exchange = payout(self.db, self.homer_route, EUR('30.00'))
         assert exchange.note is None
         assert exchange.status == 'created'
         self.homer = self.homer.refetch()
@@ -68,13 +67,13 @@ def test_payout_amount_under_minimum(self, gba):
         self.make_exchange('mango-cc', 8, 0, self.homer)
         gba.return_value = self.bank_account_outside_sepa
         with self.assertRaises(FeeExceedsAmount):
-            payout(self.db, self.homer_route, D('0.10'))
+            payout(self.db, self.homer_route, EUR('0.10'))
 
     @mock.patch('liberapay.billing.transactions.test_hook')
     def test_payout_failure(self, test_hook):
         test_hook.side_effect = Foobar
         self.make_exchange('mango-cc', 20, 0, self.homer)
-        exchange = payout(self.db, self.homer_route, D('1.00'))
+        exchange = payout(self.db, self.homer_route, EUR('1.00'))
         assert exchange.status == 'failed'
         homer = Participant.from_id(self.homer.id)
         assert exchange.note == "Foobar()"
@@ -83,13 +82,13 @@ def test_payout_failure(self, test_hook):
     def test_payout_no_route(self):
         self.make_exchange('mango-cc', 20, 0, self.david)
         with self.assertRaises(AssertionError):
-            payout(self.db, None, D('1.00'))
+            payout(self.db, None, EUR('1.00'))
 
     def test_payout_invalidated_bank_account(self):
         self.make_exchange('mango-cc', 20, 0, self.homer)
         self.homer_route.invalidate()
         with self.assertRaises(AssertionError):
-            payout(self.db, self.homer_route, D('10.00'))
+            payout(self.db, self.homer_route, EUR('10.00'))
 
     @mock.patch('mangopay.resources.BankAccount.get')
     def test_payout_quarantine(self, gba):
@@ -97,13 +96,13 @@ def test_payout_quarantine(self, gba):
         gba.return_value = self.bank_account
         with mock.patch.multiple(transactions, QUARANTINE='1 month'):
             with self.assertRaises(NotEnoughWithdrawableMoney):
-                payout(self.db, self.homer_route, D('32.00'))
+                payout(self.db, self.homer_route, EUR('32.00'))
 
     def test_payout_during_payday(self):
         self.make_exchange('mango-cc', 200, 0, self.homer)
         Payday.start()
         with self.assertRaises(PaydayIsRunning):
-            payout(self.db, self.homer_route, D('97.35'))
+            payout(self.db, self.homer_route, EUR('97.35'))
 
     def test_payout_suspended_user(self):
         self.make_exchange('mango-cc', 20, 0, self.homer)
@@ -114,7 +113,7 @@ def test_payout_suspended_user(self):
         """, (self.homer.id,))
         self.homer.set_attributes(is_suspended=True)
         with self.assertRaises(AccountSuspended):
-            payout(self.db, self.homer_route, D('10.00'))
+            payout(self.db, self.homer_route, EUR('10.00'))
 
 
 class TestCharge(MangopayHarness):
@@ -122,7 +121,7 @@ class TestCharge(MangopayHarness):
     @mock.patch('liberapay.billing.transactions.test_hook')
     def test_charge_exception(self, test_hook):
         test_hook.side_effect = Foobar
-        exchange = charge(self.db, self.janet_route, D('1.00'), 'http://localhost/')
+        exchange = charge(self.db, self.janet_route, EUR('1.00'), 'http://localhost/')
         assert exchange.note == "Foobar()"
         assert exchange.amount
         assert exchange.status == 'failed'
@@ -132,7 +131,7 @@ def test_charge_exception(self, test_hook):
     @mock.patch('mangopay.resources.PayIn.save', autospec=True)
     def test_charge_failure(self, save):
         save.side_effect = fail_payin
-        exchange = charge(self.db, self.janet_route, D('1.00'), 'http://localhost/')
+        exchange = charge(self.db, self.janet_route, EUR('1.00'), 'http://localhost/')
         error = "1: oops"
         assert exchange.note == error
         assert exchange.amount
@@ -142,7 +141,7 @@ def test_charge_failure(self, save):
 
     def test_charge_success_and_wallet_creation(self):
         self.db.run("DELETE FROM wallets WHERE owner = %s", (self.janet.id,))
-        exchange = charge(self.db, self.janet_route, D('20'), 'http://localhost/')
+        exchange = charge(self.db, self.janet_route, EUR('20'), 'http://localhost/')
         janet = Participant.from_id(self.janet.id)
         assert exchange.note is None
         assert exchange.amount == 20
@@ -160,24 +159,24 @@ def add_redirect_url_to_payin(payin):
             return payin
         save.side_effect = add_redirect_url_to_payin
         with self.assertRaises(Redirect):
-            charge(self.db, self.janet_route, D('100'), 'http://localhost/')
+            charge(self.db, self.janet_route, EUR('100'), 'http://localhost/')
         janet = Participant.from_id(self.janet.id)
         assert self.janet.balance == janet.balance == 0
 
     def test_charge_bad_card(self):
         self.janet_route.set_attributes(address='-1')
-        exchange = charge(self.db, self.janet_route, D('10.00'), 'http://localhost/')
+        exchange = charge(self.db, self.janet_route, EUR('10.00'), 'http://localhost/')
         assert exchange.note.startswith('The value -1 is not valid (CardId) | Error ID: ')
 
     def test_charge_no_card(self):
         with self.assertRaises(AssertionError):
-            charge(self.db, None, D('10.00'), 'http://localhost/')
+            charge(self.db, None, EUR('10.00'), 'http://localhost/')
 
     def test_charge_invalidated_card(self):
         bob = self.make_participant('bob')
         route = ExchangeRoute.insert(bob, 'mango-cc', '-1', error='invalidated', currency='EUR')
         with self.assertRaises(AssertionError):
-            charge(self.db, route, D('10.00'), 'http://localhost/')
+            charge(self.db, route, EUR('10.00'), 'http://localhost/')
 
     def test_charge_suspended_user(self):
         self.db.run("""
@@ -187,7 +186,7 @@ def test_charge_suspended_user(self):
         """, (self.janet.id,))
         self.janet.set_attributes(is_suspended=True)
         with self.assertRaises(AccountSuspended):
-            charge(self.db, self.janet_route, D('10.00'), 'http://localhost/')
+            charge(self.db, self.janet_route, EUR('10.00'), 'http://localhost/')
 
 
 class TestPayinBankWire(MangopayHarness):
@@ -215,7 +214,7 @@ def test_payin_bank_wire_creation(self):
     def test_payinbank_wire_exception_and_wallet_creation(self, test_hook):
         test_hook.side_effect = Foobar
         self.db.run("DELETE FROM wallets WHERE owner = %s", (self.janet.id,))
-        exchange = payin_bank_wire(self.db, self.janet, D('50'))[1]
+        exchange = payin_bank_wire(self.db, self.janet, EUR('50'))[1]
         assert exchange.note == 'Foobar()'
         assert exchange.status == 'failed'
         janet = self.janet.refetch()
@@ -224,7 +223,7 @@ def test_payinbank_wire_exception_and_wallet_creation(self, test_hook):
     @mock.patch('mangopay.resources.PayIn.save', autospec=True)
     def test_payin_bank_wire_failure(self, save):
         save.side_effect = fail_payin
-        exchange = payin_bank_wire(self.db, self.janet, D('1.00'))[1]
+        exchange = payin_bank_wire(self.db, self.janet, EUR('1.00'))[1]
         error = "1: oops"
         assert exchange.note == error
         assert exchange.amount
@@ -275,7 +274,7 @@ def test_direct_debit_creation(self, url):
     def test_direct_debit_exception_and_wallet_creation(self, test_hook):
         test_hook.side_effect = Foobar
         self.db.run("DELETE FROM wallets WHERE owner = %s", (self.homer.id,))
-        exchange = prepare_direct_debit(self.db, self.homer_route, D('50'))
+        exchange = prepare_direct_debit(self.db, self.homer_route, EUR('50'))
         assert exchange.status == 'pre-mandate'
         self.homer_route.set_mandate('-1')
         exchange = execute_direct_debit(self.db, exchange, self.homer_route)
@@ -287,7 +286,7 @@ def test_direct_debit_exception_and_wallet_creation(self, test_hook):
     @mock.patch('mangopay.resources.PayIn.save', autospec=True)
     def test_direct_debit_failure(self, save):
         save.side_effect = fail_payin
-        exchange = prepare_direct_debit(self.db, self.homer_route, D('1.00'))
+        exchange = prepare_direct_debit(self.db, self.homer_route, EUR('1.00'))
         self.homer_route.set_mandate('-2')
         exchange = execute_direct_debit(self.db, exchange, self.homer_route)
         error = "1: oops"
@@ -340,13 +339,13 @@ def test_upcharge_at_min(self):
         actual = upcharge_card(PAYIN_CARD_MIN['EUR'])
         expected = (EUR('15.54'), EUR('0.54'), EUR('0.08'))
         assert actual == expected
-        assert actual[1] / actual[0] < D('0.035')  # less than 3.5% fee
+        assert actual[1] / actual[0] < EUR('0.035')  # less than 3.5% fee
 
     def test_upcharge_at_target(self):
         actual = upcharge_card(PAYIN_CARD_TARGET['EUR'])
         expected = (EUR('94.19'), EUR('2.19'), EUR('0.32'))
         assert actual == expected
-        assert actual[1] / actual[0] < D('0.024')  # less than 2.4% fee
+        assert actual[1] / actual[0] < EUR('0.024')  # less than 2.4% fee
 
     def test_upcharge_at_one_cent(self):
         actual = upcharge_card(EUR('0.01'))
@@ -376,7 +375,7 @@ def test_record_exchange_doesnt_update_balance_for_positive_amounts(self):
             participant=self.janet, status='pre',
         )
         janet = Participant.from_username('janet')
-        assert self.janet.balance == janet.balance == D('0.00')
+        assert self.janet.balance == janet.balance == EUR('0.00')
 
     def test_record_exchange_updates_balance_for_negative_amounts(self):
         self.make_exchange('mango-cc', 50, 0, self.homer)
@@ -390,7 +389,7 @@ def test_record_exchange_updates_balance_for_negative_amounts(self):
             status='pre',
         )
         homer = Participant.from_username('homer')
-        assert homer.balance == D('13.41')
+        assert homer.balance == EUR('13.41')
 
     def test_record_exchange_fails_if_negative_balance(self):
         with pytest.raises(NegativeBalance):
@@ -400,39 +399,39 @@ def test_record_exchange_result_restores_balance_on_error(self):
         homer, ba = self.homer, self.homer_route
         self.make_exchange('mango-cc', 30, 0, homer)
         e_id = record_exchange(self.db, ba, EUR('-27.06'), EUR('0.81'), EUR(0), homer, 'pre').id
-        assert homer.balance == D('02.13')
+        assert homer.balance == EUR('02.13')
         record_exchange_result(self.db, e_id, -e_id, 'failed', 'SOME ERROR', homer)
         homer = Participant.from_username('homer')
-        assert homer.balance == D('30.00')
+        assert homer.balance == EUR('30.00')
 
     def test_record_exchange_result_restores_balance_on_error_with_invalidated_route(self):
         homer, ba = self.homer, self.homer_route
         self.make_exchange('mango-cc', 37, 0, homer)
         e_id = record_exchange(self.db, ba, EUR('-32.45'), EUR('0.86'), EUR(0), homer, 'pre').id
-        assert homer.balance == D('3.69')
+        assert homer.balance == EUR('3.69')
         ba.update_error('invalidated')
         record_exchange_result(self.db, e_id, -e_id, 'failed', 'oops', homer)
         homer = Participant.from_username('homer')
-        assert homer.balance == D('37.00')
+        assert homer.balance == EUR('37.00')
         assert ba.error == 'invalidated'
 
     def test_record_exchange_result_doesnt_restore_balance_on_success(self):
         homer, ba = self.homer, self.homer_route
         self.make_exchange('mango-cc', 50, 0, homer)
         e_id = record_exchange(self.db, ba, EUR('-43.98'), EUR('1.60'), EUR(0), homer, 'pre').id
-        assert homer.balance == D('4.42')
+        assert homer.balance == EUR('4.42')
         record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, homer)
         homer = Participant.from_username('homer')
-        assert homer.balance == D('4.42')
+        assert homer.balance == EUR('4.42')
 
     def test_record_exchange_result_updates_balance_for_positive_amounts(self):
         janet, cc = self.janet, self.janet_route
         self.make_exchange('mango-cc', 4, 0, janet)
         e_id = record_exchange(self.db, cc, EUR('31.59'), EUR('0.01'), EUR(0), janet, 'pre').id
-        assert janet.balance == D('4.00')
+        assert janet.balance == EUR('4.00')
         record_exchange_result(self.db, e_id, -e_id, 'succeeded', None, janet)
         janet = Participant.from_username('janet')
-        assert janet.balance == D('35.59')
+        assert janet.balance == EUR('35.59')
 
 
 class TestCashBundles(FakeTransfersHarness, MangopayHarness):
@@ -486,7 +485,7 @@ def test_2_sync_with_mangopay_handles_payins_that_didnt_happen(self):
              mock.patch('liberapay.billing.transactions.DirectPayIn.save', autospec=True) as save:
             rer.side_effect = save.side_effect = Foobar
             with self.assertRaises(Foobar):
-                charge(self.db, self.janet_route, D('33.67'), 'http://localhost/')
+                charge(self.db, self.janet_route, EUR('33.67'), 'http://localhost/')
         exchange = self.db.one("SELECT * FROM exchanges")
         assert exchange.status == 'pre'
         self.throw_transactions_back_in_time()
@@ -502,7 +501,7 @@ def test_5_sync_with_mangopay_reverts_payouts_that_didnt_happen(self):
              mock.patch('liberapay.billing.transactions.test_hook') as test_hook:
             rer.side_effect = test_hook.side_effect = Foobar
             with self.assertRaises(Foobar):
-                payout(self.db, self.homer_route, D('35.00'))
+                payout(self.db, self.homer_route, EUR('35.00'))
         exchange = self.db.one("SELECT * FROM exchanges WHERE amount < 0")
         assert exchange.status == 'pre'
         self.throw_transactions_back_in_time()
diff --git a/tests/py/test_public_json.py b/tests/py/test_public_json.py
--- a/tests/py/test_public_json.py
+++ b/tests/py/test_public_json.py
@@ -8,7 +8,7 @@
 class Tests(Harness):
 
     def test_anonymous(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
 
         alice.set_tip_to(bob, EUR('1.00'))
@@ -21,7 +21,7 @@ def test_anonymous(self):
         assert data['giving'] == {"amount": "1.00", "currency": "EUR"}
 
     def test_anonymous_gets_null_giving_if_user_anonymous(self):
-        alice = self.make_participant('alice', balance=100, hide_giving=True)
+        alice = self.make_participant('alice', balance=EUR(100), hide_giving=True)
         bob = self.make_participant('bob')
         alice.set_tip_to(bob, EUR('1.00'))
         data = json.loads(self.client.GET('/alice/public.json').text)
@@ -29,7 +29,7 @@ def test_anonymous_gets_null_giving_if_user_anonymous(self):
         assert data['giving'] == None
 
     def test_anonymous_gets_null_receiving_if_user_anonymous(self):
-        alice = self.make_participant('alice', balance=100, hide_receiving=True)
+        alice = self.make_participant('alice', balance=EUR(100), hide_receiving=True)
         bob = self.make_participant('bob')
         alice.set_tip_to(bob, EUR('1.00'))
         data = json.loads(self.client.GET('/alice/public.json').text)
@@ -37,28 +37,28 @@ def test_anonymous_gets_null_receiving_if_user_anonymous(self):
         assert data['receiving'] == None
 
     def test_anonymous_does_not_get_goal_if_user_regifts(self):
-        self.make_participant('alice', balance=100, goal=EUR(0))
+        self.make_participant('alice', balance=EUR(100), goal=EUR(0))
         data = json.loads(self.client.GET('/alice/public.json').text)
         assert 'goal' not in data
 
     def test_anonymous_gets_null_goal_if_user_has_no_goal(self):
-        self.make_participant('alice', balance=100)
+        self.make_participant('alice', balance=EUR(100))
         data = json.loads(self.client.GET('/alice/public.json').text)
         assert data['goal'] == None
 
     def test_anonymous_gets_user_goal_if_set(self):
-        self.make_participant('alice', balance=100, goal=EUR('1.00'))
+        self.make_participant('alice', balance=EUR(100), goal=EUR('1.00'))
         data = json.loads(self.client.GET('/alice/public.json').text)
         assert data['goal'] == {"amount": "1.00", "currency": "EUR"}
 
     def test_access_control_allow_origin_header_is_asterisk(self):
-        self.make_participant('alice', balance=100)
+        self.make_participant('alice', balance=EUR(100))
         response = self.client.GET('/alice/public.json')
 
         assert response.headers[b'Access-Control-Allow-Origin'] == b'*'
 
     def test_jsonp_works(self):
-        alice = self.make_participant('alice', balance=100)
+        alice = self.make_participant('alice', balance=EUR(100))
         bob = self.make_participant('bob')
 
         alice.set_tip_to(bob, EUR('3.00'))
diff --git a/tests/py/test_stats.py b/tests/py/test_stats.py
--- a/tests/py/test_stats.py
+++ b/tests/py/test_stats.py
@@ -11,7 +11,7 @@ class TestChartOfReceiving(Harness):
     def setUp(self):
         Harness.setUp(self)
         for participant in ['alice', 'bob']:
-            p = self.make_participant(participant, balance=100)
+            p = self.make_participant(participant, balance=EUR(100))
             setattr(self, participant, p)
 
     def test_get_tip_distribution_handles_a_tip(self):
@@ -27,7 +27,7 @@ def test_get_tip_distribution_handles_no_tips(self):
         assert actual == expected
 
     def test_get_tip_distribution_handles_multiple_tips(self):
-        carl = self.make_participant('carl', balance=100)
+        carl = self.make_participant('carl', balance=EUR(100))
         self.alice.set_tip_to(self.bob, EUR('1.00'))
         carl.set_tip_to(self.bob, EUR('3.00'))
         expected = ([
diff --git a/tests/py/test_take.py b/tests/py/test_take.py
--- a/tests/py/test_take.py
+++ b/tests/py/test_take.py
@@ -1,7 +1,5 @@
 from __future__ import unicode_literals
 
-from decimal import Decimal as D
-
 from psycopg2 import InternalError
 
 from liberapay.billing.payday import Payday
@@ -17,7 +15,7 @@ class Tests(Harness):
     def make_team(self, username=TEAM, **kw):
         team = self.make_participant(username, kind='group', **kw)
         if Participant.from_username('Daddy Warbucks') is None:
-            self.warbucks = self.make_participant('Daddy Warbucks', balance=1000)
+            self.warbucks = self.make_participant('Daddy Warbucks', balance=EUR(1000))
         self.warbucks.set_tip_to(team, EUR('100'))
         return team
 
@@ -40,11 +38,11 @@ def take_last_week(self, team, member, amount, actual_amount=None):
         team.set_take_for(member, amount, team, check_max=False)
         Payday.start()
         actual_amount = amount if actual_amount is None else actual_amount
-        if D(actual_amount) > 0:
+        if actual_amount > 0:
             self.db.run("""
                 INSERT INTO transfers (tipper, tippee, amount, context, status, team, wallet_from, wallet_to)
                 VALUES (%(tipper)s, %(tippee)s, %(amount)s, 'take', 'succeeded', %(team)s, '-1', '-2')
-            """, dict(tipper=self.warbucks.id, tippee=member.id, amount=EUR(actual_amount), team=team.id))
+            """, dict(tipper=self.warbucks.id, tippee=member.id, amount=actual_amount, team=team.id))
         self.db.run("UPDATE paydays SET ts_end=now() WHERE ts_end < ts_start")
 
     def test_random_schmoe_is_not_member_of_team(self):
@@ -58,63 +56,63 @@ def test_team_member_is_team_member(self):
 
     def test_can_take_any_amount_when_there_is_only_one_member(self):
         team, alice = self.make_team_of_one()
-        self.take_last_week(team, alice, '0.44')
-        team.set_take_for(alice, D('333.33'), alice)
-        assert team.get_take_for(alice) == D('333.33')
+        self.take_last_week(team, alice, EUR('0.44'))
+        team.set_take_for(alice, EUR('333.33'), alice)
+        assert team.get_take_for(alice) == EUR('333.33')
 
     def test_take_can_double(self):
         team, alice, bob = self.make_team_of_two()
-        self.take_last_week(team, alice, '40.00')
-        team.set_take_for(alice, D('80.00'), alice)
+        self.take_last_week(team, alice, EUR('40.00'))
+        team.set_take_for(alice, EUR('80.00'), alice)
         assert team.get_take_for(alice) == 80
 
     def test_take_can_double_but_not_a_penny_more(self):
         team, alice, bob = self.make_team_of_two()
         self.warbucks.set_tip_to(team, EUR('20'))
-        self.take_last_week(team, alice, '40.00')
-        actual = team.set_take_for(alice, D('80.01'), alice)
+        self.take_last_week(team, alice, EUR('40.00'))
+        actual = team.set_take_for(alice, EUR('80.01'), alice)
         assert actual == 80
 
     def test_increase_is_based_on_nominal_take_last_week(self):
         team, alice, bob = self.make_team_of_two()
         self.warbucks.set_tip_to(team, EUR('15.03'))
-        self.take_last_week(team, alice, '20.00', actual_amount='15.03')
-        team.set_take_for(alice, D('35.00'), team, check_max=False)
-        assert team.set_take_for(alice, D('42.00'), alice) == 40
+        self.take_last_week(team, alice, EUR('20.00'), actual_amount=EUR('15.03'))
+        team.set_take_for(alice, EUR('35.00'), team, check_max=False)
+        assert team.set_take_for(alice, EUR('42.00'), alice) == 40
 
     def test_if_last_week_is_less_than_one_can_increase_to_one(self):
         team, alice, bob = self.make_team_of_two()
         self.warbucks.set_tip_to(team, EUR('0.50'))
-        self.take_last_week(team, alice, '0.01')
-        actual = team.set_take_for(alice, D('42.00'), team)
+        self.take_last_week(team, alice, EUR('0.01'))
+        actual = team.set_take_for(alice, EUR('42.00'), team)
         assert actual == 1
 
     def test_can_take_any_amount_when_takes_were_all_zero_last_week(self):
         team, alice, bob = self.make_team_of_two()
-        self.take_last_week(team, alice, '0.00')
-        self.take_last_week(team, bob, '0.00')
-        actual = team.set_take_for(alice, D('222.00'), team)
+        self.take_last_week(team, alice, EUR('0.00'))
+        self.take_last_week(team, bob, EUR('0.00'))
+        actual = team.set_take_for(alice, EUR('222.00'), team)
         assert actual == 222
 
     def test_can_take_leftover(self):
         team, alice, bob = self.make_team_of_two()
-        self.take_last_week(team, alice, '0.01')
-        actual = team.set_take_for(alice, D('200.00'), team)
+        self.take_last_week(team, alice, EUR('0.01'))
+        actual = team.set_take_for(alice, EUR('200.00'), team)
         assert actual == 100
 
     def test_can_take_any_amount_when_throttling_is_disabled(self):
         team, alice, bob = self.make_team_of_two(throttle_takes=False)
-        self.take_last_week(team, alice, '0.00')
-        team.set_take_for(alice, D('400.00'), alice)
+        self.take_last_week(team, alice, EUR('0.00'))
+        team.set_take_for(alice, EUR('400.00'), alice)
         assert team.get_take_for(alice) == 400
-        self.take_last_week(team, alice, '10.00')
-        team.set_take_for(alice, D('500.00'), alice)
+        self.take_last_week(team, alice, EUR('10.00'))
+        team.set_take_for(alice, EUR('500.00'), alice)
         assert team.get_take_for(alice) == 500
 
     def test_get_members(self):
         team, alice = self.make_team_of_one()
-        self.take_last_week(team, alice, '40.00')
-        team.set_take_for(alice, D('42.00'), team)
+        self.take_last_week(team, alice, EUR('40.00'))
+        team.set_take_for(alice, EUR('42.00'), team)
         members = team.get_members()
         assert len(members) == 1
         assert members[alice.id]['username'] == 'alice'
@@ -123,9 +121,9 @@ def test_get_members(self):
 
     def test_taking_and_receiving_are_updated_correctly(self):
         team, alice = self.make_team_of_one()
-        self.take_last_week(team, alice, '40.00')
+        self.take_last_week(team, alice, EUR('40.00'))
         self.warbucks.set_tip_to(team, EUR('42.00'))
-        team.set_take_for(alice, D('42.00'), alice)
+        team.set_take_for(alice, EUR('42.00'), alice)
         assert alice.taking == 42
         assert alice.receiving == 42
         self.warbucks.set_tip_to(alice, EUR('10.00'))
@@ -133,7 +131,7 @@ def test_taking_and_receiving_are_updated_correctly(self):
         assert alice.receiving == 52
         self.warbucks.set_tip_to(team, EUR('50.00'))
         assert team.receiving == 50
-        team.set_take_for(alice, D('50.00'), alice)
+        team.set_take_for(alice, EUR('50.00'), alice)
         assert alice.taking == 50
         assert alice.receiving == 60
 
@@ -152,8 +150,8 @@ def test_team_cant_take_from_other_team(self):
 
     def test_changes_to_team_receiving_affect_members_take(self):
         team, alice = self.make_team_of_one()
-        self.take_last_week(team, alice, '40.00')
-        team.set_take_for(alice, D('42.00'), alice)
+        self.take_last_week(team, alice, EUR('40.00'))
+        team.set_take_for(alice, EUR('42.00'), alice)
 
         self.warbucks.set_tip_to(team, EUR('10.00'))  # hard times
         alice = Participant.from_username('alice')
@@ -162,11 +160,11 @@ def test_changes_to_team_receiving_affect_members_take(self):
     def test_changes_to_others_take_affects_members_take(self):
         team, alice, bob = self.make_team_of_two()
 
-        self.take_last_week(team, alice, '30.00')
-        team.set_take_for(alice, D('40.00'), alice)
+        self.take_last_week(team, alice, EUR('30.00'))
+        team.set_take_for(alice, EUR('40.00'), alice)
 
-        self.take_last_week(team, bob, '50.00')
-        team.set_take_for(bob, D('60.00'), bob)
+        self.take_last_week(team, bob, EUR('50.00'))
+        team.set_take_for(bob, EUR('60.00'), bob)
 
         alice = Participant.from_username('alice')
         assert alice.receiving == alice.taking == 40
@@ -177,15 +175,15 @@ def test_changes_to_others_take_affects_members_take(self):
     def test_changes_to_others_take_can_increase_members_take(self):
         team, alice, bob = self.make_team_of_two()
 
-        self.take_last_week(team, alice, '30.00')
-        team.set_take_for(alice, D('25.00'), alice)
+        self.take_last_week(team, alice, EUR('30.00'))
+        team.set_take_for(alice, EUR('25.00'), alice)
 
-        self.take_last_week(team, bob, '50.00')
-        team.set_take_for(bob, D('100.00'), bob)
+        self.take_last_week(team, bob, EUR('50.00'))
+        team.set_take_for(bob, EUR('100.00'), bob)
         alice = Participant.from_username('alice')
         assert alice.receiving == alice.taking == 20
 
-        team.set_take_for(bob, D('75.00'), bob)
+        team.set_take_for(bob, EUR('75.00'), bob)
         alice = Participant.from_username('alice')
         assert alice.receiving == alice.taking == 25
 
@@ -193,16 +191,16 @@ def test_changes_to_others_take_can_increase_members_take(self):
 
     def test_gtlwf_works_during_payday(self):
         team, alice = self.make_team_of_one()
-        self.take_last_week(team, alice, '20.00')
+        self.take_last_week(team, alice, EUR('20.00'))
         assert team.get_takes_last_week()[alice.id] == 20
-        self.take_last_week(team, alice, '30.00')
+        self.take_last_week(team, alice, EUR('30.00'))
         assert team.get_takes_last_week()[alice.id] == 30
-        take_this_week = D('42.00')
+        take_this_week = EUR('42.00')
         team.set_take_for(alice, take_this_week, alice)
         Payday.start()
         assert team.get_takes_last_week()[alice.id] == 30
         self.db.run("""
             INSERT INTO transfers (tipper, tippee, amount, context, status, team, wallet_from, wallet_to)
             VALUES (%(tipper)s, %(id)s, %(amount)s, 'take', 'succeeded', %(team)s, '-1', '-2')
-        """, dict(tipper=self.warbucks.id, id=alice.id, amount=EUR(take_this_week), team=team.id))
+        """, dict(tipper=self.warbucks.id, id=alice.id, amount=take_this_week, team=team.id))
         assert team.get_takes_last_week()[alice.id] == 30
diff --git a/tests/py/test_tip_json.py b/tests/py/test_tip_json.py
--- a/tests/py/test_tip_json.py
+++ b/tests/py/test_tip_json.py
@@ -24,7 +24,7 @@ def test_get_amount_and_total_back_from_api(self):
         # We need accounts
         self.make_participant("test_tippee1")
         self.make_participant("test_tippee2")
-        test_tipper = self.make_participant("test_tipper", balance=100)
+        test_tipper = self.make_participant("test_tipper", balance=EUR(100))
 
         # Then, add a $1.50 and $3.00 tip
         response1 = self.tip(test_tipper, "test_tippee1", "1.00")