Skip to content

Support minimum balance calculations for boxes with native helpers #226

@kylebeee

Description

@kylebeee

Problem

Sometimes box MBR calculations are simple: 2_500 + ((key.length + value.length) * 400). Other times MBR calculation becomes a pain & ends up costing you substantial time & effort as you work through MBR calculations with named tuples that contain dynamic length values. Now we're dealing with offset bytes & length bytes & sometimes multiple dynamic values across both our keys & box values. It can get hairy & its something small you end up repetitively having to manage.

Solution

If possible it would be fantastic to offer native helpers for MBR box calculations exposed as methods on our Box & BoxMap types.

Proposal

At the moment I think the best signature for this would look something like

interface BoxMap<TKey, TValue> {
  mbr(params: {
    key?: TKey
    value?: StripStaticTypes<TValue>
  }): { cost: uint64; isNegative: boolean };
}

The idea being that the puya compiler precomputes all static portions of the box values & only takes in the dynamic properties of named tuples or other compound types for calculating the MBR.

If the key provided already exists the function would return the MBR diff & would use the isNegative property to indicate whether the cost value would be additive or subtractive.

usage could look something like:

type Foo = {
  title: string
  count: uint64
}

export class FooContract extends Contract {

  // ...

  fooBoxes = BoxMap<uint64, Foo>({ keyPrefix: 'f' })

  // ...

  foo(title: string, payment: gtxn.PaymentTxn) {
    const newKey = this.incrementFoo();
    const newValue: Foo = { title, count: 1 }
    const { cost } = this.fooBoxes.mbr({ key: newKey, value: newValue });

    assertMatch(
      payment,
      {
        receiver: Global.currentApplicationAddress,
        amount: cost,
      }
    )

    this.fooBoxes(newKey).value = newValue;
  }

  bar(id: uint64, newTitle: string) {
    assert(this.fooBoxes(id).exists, `foo doesn't exist`)
    const { cost, isNegative } = this.fooBoxes.mbr({ key: id, value: { title: newTitle }});

    // ...
  }
}

This could help substantially with getting new users started and getting box allocation MBRs out of the way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions