Skip to content

Commit

Permalink
feat(balances): latest implementation (#420)
Browse files Browse the repository at this point in the history
* wip(balances): latest implementation

* fix(balances): logic, tests and metadata

* style: imports

* refactor(system/storage): account default value

* fix benchmarks

* fix existing tests

* balances tests

---------

Co-authored-by: Rado M <[email protected]>
  • Loading branch information
failfmi and radkomih authored Jun 14, 2024
1 parent 2d3bcf2 commit 095050b
Show file tree
Hide file tree
Showing 118 changed files with 4,392 additions and 4,508 deletions.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ start-network-babe:
cd ../../../..; \
WASMTIME_BACKTRACE_DETAILS=1 RUST_LOG=runtime=trace ./target/release/substrate-node --dev --execution=wasm

start-network:
cp build/runtime.wasm polkadot-sdk/substrate/bin/node-template/runtime.wasm; \
cd polkadot-sdk/substrate/bin/node-template/node; \
cargo build --release; \
cd ../../../..; \
WASMTIME_BACKTRACE_DETAILS=1 RUST_LOG=runtime=trace ./target/release/node-template --dev --execution=wasm

# gossamer node configuration
CHAIN_SPEC_PLAIN = ../testdata/chain-spec/plain.json
CHAIN_SPEC_UPDATED = ../testdata/chain-spec/plain-updated.json
Expand Down
3 changes: 2 additions & 1 deletion api/benchmarking/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,15 @@ func (m Module) originAndMaybeAccount(benchmarkConfig benchmarking.BenchmarkConf

func (m Module) whitelistWellKnownKeys() {
keySystemHash := m.hashing.Twox128([]byte("System"))
keyBalancesHash := m.hashing.Twox128([]byte("Balances"))
keyBlockWeight := m.hashing.Twox128([]byte("BlockWeight"))
keyExecutionPhaseHash := m.hashing.Twox128([]byte("ExecutionPhase"))
keyEventCountHash := m.hashing.Twox128([]byte("EventCount"))
keyEventsHash := m.hashing.Twox128([]byte("Events"))
keyNumberHash := m.hashing.Twox128([]byte("Number"))
keyTotalIssuanceHash := m.hashing.Twox128([]byte("TotalIssuance"))

benchmarking.SetWhitelist(append(keySystemHash, keyTotalIssuanceHash...))
benchmarking.SetWhitelist(append(keyBalancesHash, keyTotalIssuanceHash...))
benchmarking.SetWhitelist(append(keySystemHash, keyBlockWeight...))
benchmarking.SetWhitelist(append(keySystemHash, keyNumberHash...))
benchmarking.SetWhitelist(append(keySystemHash, keyExecutionPhaseHash...))
Expand Down
41 changes: 32 additions & 9 deletions api/metadata/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
primitives.NewMetadataTypeDefinitionComposite(sc.Sequence[primitives.MetadataTypeDefinitionField]{
primitives.NewMetadataTypeDefinitionField(metadata.TypesFixedSequence32U8)})),

primitives.NewMetadataType(
metadata.TypesCompactU128,
"compact U128",
primitives.NewMetadataTypeDefinitionCompact(
sc.ToCompact(metadata.PrimitiveTypesU128),
),
),

primitives.NewMetadataTypeWithPath(metadata.TypesAddress32, "Address32", sc.Sequence[sc.Str]{"sp_core", "crypto", "AccountId32"}, primitives.NewMetadataTypeDefinitionComposite(
sc.Sequence[primitives.MetadataTypeDefinitionField]{primitives.NewMetadataTypeDefinitionFieldWithName(metadata.TypesFixedSequence32U8, "[u8; 32]")},
)),
Expand Down Expand Up @@ -337,8 +345,8 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
sc.Sequence[primitives.MetadataTypeDefinitionField]{
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "free", "Balance"),
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "reserved", "Balance"),
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "misc_frozen", "Balance"),
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "fee_frozen", "Balance"),
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "frozen", "Balance"),
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU128, "flags", "ExtraFlags"),
},
)),
primitives.NewMetadataTypeWithPath(metadata.TypesAccountInfo, "AccountInfo", sc.Sequence[sc.Str]{"frame_system", "AccountInfo"}, primitives.NewMetadataTypeDefinitionComposite(
Expand Down Expand Up @@ -591,17 +599,17 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
primitives.NewMetadataTypeWithPath(metadata.TypesTokenError, "TokenError", sc.Sequence[sc.Str]{"sp_runtime", "TokenError"}, primitives.NewMetadataTypeDefinitionVariant(
sc.Sequence[primitives.MetadataDefinitionVariant]{
primitives.NewMetadataDefinitionVariant(
"NoFunds",
"FundsUnavailable",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorNoFunds,
"TokenError.NoFunds"),
primitives.TokenErrorFundsUnavailable,
"TokenError.FundsUnavailable"),
primitives.NewMetadataDefinitionVariant(
"WouldDie",
"OnlyProvider",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorWouldDie,
"TokenError.WouldDie"),
primitives.TokenErrorOnlyProvider,
"TokenError.OnlyProvider"),
primitives.NewMetadataDefinitionVariant(
"Mandatory",
"BelowMinimum",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorBelowMinimum,
"TokenError.BelowMinimum"),
Expand All @@ -625,6 +633,21 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorUnsupported,
"TokenError.Unsupported"),
primitives.NewMetadataDefinitionVariant(
"CannotCreateHold",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorCannotCreateHold,
"TokenError.CannotCreateHold"),
primitives.NewMetadataDefinitionVariant(
"NotExpendable",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorNotExpendable,
"TokenError.NotExpendable"),
primitives.NewMetadataDefinitionVariant(
"Blocked",
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
primitives.TokenErrorBlocked,
"TokenError.Blocked"),
})),
primitives.NewMetadataTypeWithPath(metadata.TypesArithmeticError, "ArithmeticError", sc.Sequence[sc.Str]{"sp_arithmetic", "ArithmeticError"}, primitives.NewMetadataTypeDefinitionVariant(
sc.Sequence[primitives.MetadataDefinitionVariant]{
Expand Down
Binary file modified build/runtime-benchmarks.wasm
Binary file not shown.
Binary file modified build/runtime.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions constants/currency.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ const (

var (
Zero = sc.NewU128(0)
One = sc.NewU128(1)
DefaultTip = Zero
)
1 change: 1 addition & 0 deletions constants/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (

TypesBalancesEvent
TypesBalanceStatus
TypesBalancesAdjustDirection
TypesVecTopics
TypesLastRuntimeUpgradeInfo
TypesSystemErrors
Expand Down
135 changes: 135 additions & 0 deletions frame/balances/call_force_adjust_total_issuance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package balances

import (
"bytes"

sc "github.com/LimeChain/goscale"
"github.com/LimeChain/gosemble/constants"
"github.com/LimeChain/gosemble/frame/balances/types"
primitives "github.com/LimeChain/gosemble/primitives/types"
)

type callForceAdjustTotalIssuance struct {
primitives.Callable
storage *storage
eventDepositor primitives.EventDepositor
}

func newCallForceAdjustTotalIssuance(moduleId sc.U8, functionId sc.U8, eventDepositor primitives.EventDepositor, storage *storage) primitives.Call {
return callForceAdjustTotalIssuance{
Callable: primitives.Callable{
ModuleId: moduleId,
FunctionId: functionId,
Arguments: sc.NewVaryingData(types.AdjustDirection{}, sc.Compact{Number: sc.U128{}}),
},
eventDepositor: eventDepositor,
storage: storage,
}
}

func (c callForceAdjustTotalIssuance) DecodeArgs(buffer *bytes.Buffer) (primitives.Call, error) {
direction, err := types.DecodeAdjustDirection(buffer)
if err != nil {
return nil, err
}
delta, err := sc.DecodeCompact[sc.U128](buffer)
if err != nil {
return nil, err
}
c.Arguments = sc.NewVaryingData(
direction,
delta,
)

return c, nil
}

func (c callForceAdjustTotalIssuance) Encode(buffer *bytes.Buffer) error {
return c.Callable.Encode(buffer)
}

func (c callForceAdjustTotalIssuance) Bytes() []byte {
return c.Callable.Bytes()
}

func (c callForceAdjustTotalIssuance) ModuleIndex() sc.U8 { return c.Callable.ModuleIndex() }

func (c callForceAdjustTotalIssuance) FunctionIndex() sc.U8 { return c.Callable.FunctionIndex() }

func (c callForceAdjustTotalIssuance) Args() sc.VaryingData { return c.Callable.Args() }

func (c callForceAdjustTotalIssuance) BaseWeight() primitives.Weight {
return callForceAdjustTotalIssuanceWeight()
}

func (_ callForceAdjustTotalIssuance) WeighData(baseWeight primitives.Weight) primitives.Weight {
return primitives.WeightFromParts(baseWeight.RefTime, 0)
}

func (_ callForceAdjustTotalIssuance) ClassifyDispatch(baseWeight primitives.Weight) primitives.DispatchClass {
return primitives.NewDispatchClassNormal()
}

func (_ callForceAdjustTotalIssuance) PaysFee(baseWeight primitives.Weight) primitives.Pays {
return primitives.PaysYes
}

func (_ callForceAdjustTotalIssuance) Docs() string {
return "Adjust the total issuance in a saturating way. Can only be called by root and always needs a positive `delta`."
}

func (c callForceAdjustTotalIssuance) Dispatch(origin primitives.RuntimeOrigin, args sc.VaryingData) (primitives.PostDispatchInfo, error) {
if !origin.IsRootOrigin() {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorBadOrigin()
}
direction, ok := args[0].(types.AdjustDirection)
if !ok {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther("invalid direction value when dispatching callForceAdjustTotalIssuance")
}
deltaCompact, ok := args[1].(sc.Compact)
if !ok {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther("invalid amount value when dispatching call force free")
}

delta, ok := deltaCompact.Number.(sc.U128)
if !ok {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther("invalid Compact field delta when dispatch call_force_adjust_total_issuance")
}

if delta.Lte(constants.Zero) {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorModule(primitives.CustomModuleError{
Index: c.ModuleId,
Err: sc.U32(ErrorDeltaZero),
Message: sc.NewOption[sc.Str](nil),
})
}

totalIssuance, err := c.storage.TotalIssuance.Get()
if err != nil {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther(sc.Str(err.Error()))
}

var newIssuance sc.U128
if direction.IsIncrease() {
newIssuance = sc.SaturatingAddU128(totalIssuance, delta)
} else {
newIssuance = sc.SaturatingSubU128(totalIssuance, delta)
}

inactiveIssuance, err := c.storage.InactiveIssuance.Get()
if err != nil {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther(sc.Str(err.Error()))
}

if inactiveIssuance.Gt(newIssuance) {
return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorModule(primitives.CustomModuleError{
Index: c.ModuleId,
Err: sc.U32(ErrorIssuanceDeactivated),
Message: sc.NewOption[sc.Str](nil),
})
}
c.storage.TotalIssuance.Put(newIssuance)
c.eventDepositor.DepositEvent(newEventTotalIssuanceForced(c.ModuleId, totalIssuance, newIssuance))

return primitives.PostDispatchInfo{}, nil
}
7 changes: 7 additions & 0 deletions frame/balances/call_force_adjust_total_issuance_weight.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package balances

import primitives "github.com/LimeChain/gosemble/primitives/types"

func callForceAdjustTotalIssuanceWeight() primitives.Weight {
return primitives.WeightFromParts(6507000, 0)
}
Loading

0 comments on commit 095050b

Please sign in to comment.