Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions builder/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ func SrcColored(
}
}

// SrcAllowingUnboundedOverdraft wraps a source (typically SrcAccount or
// SrcColored) and appends the `allowing unbounded overdraft` clause, per the
// Numscript grammar rule `srcAccountUnboundedOverdraft`
// (address colorConstraint? ALLOWING UNBOUNDED OVERDRAFT). It lets a non-world
// source go negative — required, for instance, when minting a colour the
// account does not yet hold.
func SrcAllowingUnboundedOverdraft(source Source) Source {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [major] Restrict overdraft combinator to account sources

When callers wrap any composite source such as SrcInorder(...) or SrcCapped(...), this exported API still appends allowing unbounded overdraft, producing scripts like { ... } allowing unbounded overdraft or max ... from ... allowing unbounded overdraft that the Numscript grammar cannot parse. The clause is only valid on the account/color source form, so the builder should avoid accepting arbitrary Source values here or otherwise prevent invalid compositions.

return func(env *env, w int) {
source(env, w)
env.builder.WriteString(" allowing unbounded overdraft")
}
}

func SrcInorder(sources ...Source) Source {
return func(env *env, w int) {
env.builder.WriteString("{\n")
Expand Down
40 changes: 40 additions & 0 deletions builder/source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package builder_test

import (
"math/big"
"testing"

"github.com/formancehq/numscript/builder"
"github.com/gkampitakis/go-snaps/snaps"
)

func TestSrcAllowingUnboundedOverdraft(t *testing.T) {
stmt := builder.StmtSend(
builder.ExprMonetary(
builder.ExprAsset("USD/2"),
builder.ExprNumberBigInt(big.NewInt(100)),
),
builder.SrcAllowingUnboundedOverdraft(
builder.SrcColored(
builder.ExprAccount("tmp:acc"),
builder.ExprString("ABCDEF"),
),
),
builder.DestAccount(
builder.ExprAccount("dest"),
),
)

_, _, script := builder.BuildProgram(stmt)
snaps.MatchInlineSnapshot(t, script, snaps.Inline(`vars {
account $account_0
account $account_1
string $string_0
asset $asset_0
}

send [$asset_0 100] (
source = $account_0 \ $string_0 allowing unbounded overdraft
destination = $account_1
)`))
}