Skip to content

Commit 1293e89

Browse files
committed
fix: reject duplicate remaining allotments
1 parent 5cc059f commit 1293e89

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

internal/interpreter/interpreter.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,9 +1029,13 @@ func (s *programState) makeAllotment(monetary *big.Int, items []parser.Allotment
10291029
allotments = append(allotments, rat)
10301030

10311031
case *parser.RemainingAllotment:
1032+
if remainingAllotmentIndex != -1 {
1033+
return nil, InvalidRemainingAllotment{
1034+
Range: allotment.Range,
1035+
}
1036+
}
10321037
remainingAllotmentIndex = i
10331038
allotments = append(allotments, new(big.Rat))
1034-
// TODO check there are not duplicate remaining clause
10351039
}
10361040
}
10371041

internal/interpreter/interpreter_error.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ func (e InvalidAllotmentInSendAll) Error() string {
153153
return "cannot take all balance of an allotment source"
154154
}
155155

156+
type InvalidRemainingAllotment struct {
157+
parser.Range
158+
}
159+
160+
func (e InvalidRemainingAllotment) Error() string {
161+
return "Only one 'remaining' clause is allowed in an allotment expression"
162+
}
163+
156164
type DivideByZero struct {
157165
parser.Range
158166
Numerator *big.Int

numscript_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,27 @@ func TestGetVarsNovars(t *testing.T) {
5858
)
5959
}
6060

61+
func TestRunRejectsDuplicateRemainingAllotments(t *testing.T) {
62+
parseResult := numscript.Parse(`send [COIN 100] (
63+
source = {
64+
remaining from @a
65+
remaining from @b
66+
}
67+
destination = @dest
68+
)
69+
`)
70+
require.Empty(t, parseResult.GetParsingErrors())
71+
72+
_, err := parseResult.Run(context.Background(), numscript.VariablesMap{}, interpreter.StaticStore{
73+
Balances: interpreter.Balances{
74+
"a": {"COIN": big.NewInt(100)},
75+
"b": {"COIN": big.NewInt(100)},
76+
},
77+
})
78+
require.Error(t, err)
79+
require.Contains(t, err.Error(), "remaining")
80+
}
81+
6182
func TestDoNotGetWorldBalance(t *testing.T) {
6283
parseResult := numscript.Parse(`send [COIN 100] (
6384
source = @world

0 commit comments

Comments
 (0)