diff --git a/pkg/core/funding.go b/pkg/core/funding.go index fd5231593..b5452ef4c 100644 --- a/pkg/core/funding.go +++ b/pkg/core/funding.go @@ -53,6 +53,12 @@ func (f Funding) Take(amount *MonetaryInt) (Funding, Funding, error) { remainder := Funding{ Asset: f.Asset, } + if amount.Eq(NewMonetaryInt(0)) && len(f.Parts) > 0 { + result.Parts = append(result.Parts, FundingPart{ + Account: f.Parts[0].Account, + Amount: amount, + }) + } remainingToWithdraw := amount i := 0 for remainingToWithdraw.Gt(NewMonetaryInt(0)) && i < len(f.Parts) { diff --git a/pkg/ledger/execute_script_test.go b/pkg/ledger/execute_script_test.go index ce4282130..b18de545e 100644 --- a/pkg/ledger/execute_script_test.go +++ b/pkg/ledger/execute_script_test.go @@ -107,10 +107,10 @@ func TestSend(t *testing.T) { )`, }, } - _, err := l.ExecuteScript(context.Background(), false, script) - require.Error(t, err) - require.True(t, ledger.IsValidationError(err)) - require.ErrorContains(t, err, "transaction has no postings") + res, err := l.ExecuteScript(context.Background(), false, script) + require.NoError(t, err) + + require.Equal(t, 1, len(res.Postings)) }) t.Run("one send with monetary all should fail", func(t *testing.T) { @@ -123,10 +123,10 @@ func TestSend(t *testing.T) { )`, }, } - _, err := l.ExecuteScript(context.Background(), false, script) - require.Error(t, err) - require.True(t, ledger.IsValidationError(err)) - require.ErrorContains(t, err, "transaction has no postings") + res, err := l.ExecuteScript(context.Background(), false, script) + require.NoError(t, err) + + require.Equal(t, 1, len(res.Postings)) }) t.Run("one send with zero amount and another with positive amount should succeed", func(t *testing.T) { @@ -145,7 +145,7 @@ func TestSend(t *testing.T) { } res, err := l.ExecuteScript(context.Background(), false, script) require.NoError(t, err) - require.Equal(t, 1, len(res.Postings)) + require.Equal(t, 2, len(res.Postings)) assertBalance(t, l, "user:001", "USD/2", core.NewMonetaryInt(100)) @@ -167,7 +167,7 @@ func TestSend(t *testing.T) { } res, err := l.ExecuteScript(context.Background(), false, script) require.NoError(t, err) - require.Equal(t, 1, len(res.Postings)) + require.Equal(t, 2, len(res.Postings)) assertBalance(t, l, "user:001", "USD/2", core.NewMonetaryInt(101)) diff --git a/pkg/machine/vm/machine.go b/pkg/machine/vm/machine.go index 0666e113e..9cacab414 100644 --- a/pkg/machine/vm/machine.go +++ b/pkg/machine/vm/machine.go @@ -416,9 +416,6 @@ func (m *Machine) tick() (bool, byte, error) { for _, part := range funding.Parts { src := part.Account amt := part.Amount - if amt.Eq(core.NewMonetaryInt(0)) { - continue - } m.Postings = append(m.Postings, Posting{ Source: string(src), Destination: string(dest), diff --git a/pkg/machine/vm/machine_test.go b/pkg/machine/vm/machine_test.go index dea3d8701..e23c2575e 100644 --- a/pkg/machine/vm/machine_test.go +++ b/pkg/machine/vm/machine_test.go @@ -207,6 +207,28 @@ func TestSend(t *testing.T) { test(t, tc) } +func TestSend0Amount(t *testing.T) { + tc := NewTestCase() + tc.compile(t, `send [EUR/2 0] ( + source=@alice + destination=@bob + )`) + tc.setBalance("alice", "EUR/2", 100) + tc.expected = CaseResult{ + Printed: []core.Value{}, + Postings: []Posting{ + { + Asset: "EUR/2", + Amount: core.NewMonetaryInt(0), + Source: "alice", + Destination: "bob", + }, + }, + ExitCode: EXIT_OK, + } + test(t, tc) +} + func TestVariables(t *testing.T) { tc := NewTestCase() tc.compile(t, `vars { @@ -555,7 +577,7 @@ func TestNoEmptyPostings(t *testing.T) { test(t, tc) } -func TestNoEmptyPostings2(t *testing.T) { +func TestEmptyPostings(t *testing.T) { tc := NewTestCase() tc.compile(t, `send [GEM *] ( source = @foo @@ -563,8 +585,15 @@ func TestNoEmptyPostings2(t *testing.T) { )`) tc.setBalance("foo", "GEM", 0) tc.expected = CaseResult{ - Printed: []core.Value{}, - Postings: []Posting{}, + Printed: []core.Value{}, + Postings: []Posting{ + { + Source: "foo", + Destination: "bar", + Amount: core.NewMonetaryInt(0), + Asset: "GEM", + }, + }, ExitCode: EXIT_OK, } test(t, tc)