Skip to content
Draft
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e5725b8
initial proof of concept
nullun Aug 19, 2024
d837ec2
afrz transactions are used to configure global freeze
nullun Aug 20, 2024
d6a6e25
minor text/key name changes
nullun Aug 21, 2024
436d2c2
Update goal and API responses
nullun Mar 28, 2025
849f2d4
Remove gfrz field from afrz transaction
nullun Apr 3, 2025
c4ea51a
Remove unused flag in 'goal asset freeze'
nullun Apr 3, 2025
1d1044d
Change GlobalFreeze codec from '0' to 'G'
nullun Apr 3, 2025
e0954a4
update "asset_holding_get" and "asset_params_get" opcodes
ori-shem-tov Apr 3, 2025
7232431
Merge pull request #2 from ori-shem-tov/feature/asa-global-freeze
nullun Apr 3, 2025
7d41877
Update and regen langspec and readme
nullun Apr 4, 2025
3e7d594
Fix 'asset_holding_get AssetFrozen' backwards compatibility, if asset…
nullun Apr 4, 2025
a4716ea
Allow asset holding to be unfrozen whilst asset params are globally f…
nullun Apr 8, 2025
f8db258
Updates following review
nullun Apr 11, 2025
4f19688
use existing vfuture consensus
nullun Apr 14, 2025
3af7cc0
use existing pattern for returning default values
nullun Apr 14, 2025
e11abe8
Rename function and provide context
nullun Apr 14, 2025
b82ceae
API: Expose frozen boolean and remove last freeze uint64
nullun Apr 15, 2025
d1bf5b1
merge latest master into feature branch
nullun Apr 15, 2025
7e6911a
Add wellFormed() for all asset transaction types
nullun Apr 15, 2025
20c3770
TEAL: Hide uint64 fields, expose boolean
nullun Apr 15, 2025
f121e8b
Update ledger field keys
nullun Apr 15, 2025
292a68f
Reverted opdoc to v11, removing all TEAL v12 output
nullun Apr 15, 2025
592554d
Added various tests
nullun May 13, 2025
d8f4bf5
Merge branch 'master' into feature/asa-global-freeze
nullun May 14, 2025
78593ec
regenerate algod api
nullun May 14, 2025
6cdd2b1
Additional test for unfreezing an individual
nullun May 14, 2025
b5c5d5d
Fix the gated empty FreezeAccount wellFormed check
nullun May 14, 2025
980bed3
added two new fields LastGlobalFreeze and LastFreezeChange
nullun May 19, 2025
09be117
Set new field values 1 in 5 times
nullun May 21, 2025
f0d8ea7
Merge branch 'master' into feature/asa-global-freeze
nullun May 21, 2025
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
2 changes: 2 additions & 0 deletions cmd/goal/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,8 @@ func printAccountInfo(client libgoal.Client, address string, onlyShowAssetIDs bo
frozen := ""
if assetHolding.IsFrozen {
frozen = " (frozen)"
} else if assetParams.Params.Frozen != nil {
frozen = " (globally frozen)"
}

fmt.Fprintf(report, "\tID %d, %s, balance %s %s%s\n", assetHolding.AssetID, assetName, amount, unitName, frozen)
Expand Down
2 changes: 1 addition & 1 deletion cmd/goal/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ func init() {
freezeAssetCmd.Flags().StringVar(&account, "account", "", "Account address to freeze/unfreeze")
freezeAssetCmd.Flags().BoolVar(&assetFrozen, "freeze", false, "Freeze or unfreeze")
freezeAssetCmd.MarkFlagRequired("freezer")
freezeAssetCmd.MarkFlagRequired("account")
freezeAssetCmd.MarkFlagRequired("freeze")

optinAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of the asset being accepted")
Expand Down Expand Up @@ -806,6 +805,7 @@ var infoAssetCmd = &cobra.Command{
fmt.Printf("Issued: %s %s\n", assetDecimalsFmt(asset.Params.Total-res.Amount, asset.Params.Decimals), derefString(asset.Params.UnitName))
fmt.Printf("Decimals: %d\n", asset.Params.Decimals)
fmt.Printf("Default frozen: %v\n", derefBool(asset.Params.DefaultFrozen))
fmt.Printf("Global freeze: %v\n", derefBool(asset.Params.Frozen))
fmt.Printf("Manager address: %s\n", derefString(asset.Params.Manager))
if reserveEmpty {
fmt.Printf("Reserve address: %s (Empty. Defaulting to creator)\n", derefString(asset.Params.Reserve))
Expand Down
6 changes: 6 additions & 0 deletions config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,11 @@ type ConsensusParams struct {

// Heartbeat support
Heartbeat bool

// Allow for afrz transactions to target the zero address, freezing that
// asset for all holders. Subsequent unfreezing of an individuals holdings
// allows them to transfer the asset again.
EnableGlobalFreeze bool
}

// ProposerPayoutRules puts several related consensus parameters in one place. The same
Expand Down Expand Up @@ -1552,6 +1557,7 @@ func initConsensusProtocols() {
vFuture.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}

vFuture.LogicSigVersion = 12 // When moving this to a release, put a new higher LogicSigVersion here
vFuture.EnableGlobalFreeze = true

Consensus[protocol.ConsensusFuture] = vFuture

Expand Down
4 changes: 4 additions & 0 deletions daemon/algod/api/algod.oas2.json
Original file line number Diff line number Diff line change
Expand Up @@ -3377,6 +3377,10 @@
"description": "\\[f\\] Address of account used to freeze holdings of this asset. If empty, freezing is not permitted.",
"type": "string"
},
"frozen": {
"description": "\\[fr\\] Whether this asset is frozen.",
"type": "boolean"
},
"manager": {
"description": "\\[m\\] Address of account used to manage the keys of this asset and to destroy it.",
"type": "string"
Expand Down
4 changes: 4 additions & 0 deletions daemon/algod/api/algod.oas3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,10 @@
"description": "\\[f\\] Address of account used to freeze holdings of this asset. If empty, freezing is not permitted.",
"type": "string"
},
"frozen": {
"description": "\\[fr\\] Whether this asset is frozen.",
"type": "boolean"
},
"manager": {
"description": "\\[m\\] Address of account used to manage the keys of this asset and to destroy it.",
"type": "string"
Expand Down
30 changes: 19 additions & 11 deletions daemon/algod/api/server/v2/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ func AccountToAccountData(a *model.Account) (basics.AccountData, error) {
if ca.Params.DefaultFrozen != nil {
defaultFrozen = *ca.Params.DefaultFrozen
}
var lastGlobalFreeze uint64
if ca.Params.Frozen != nil {
// model.Asset doesn't know the LastGlobalFreeze value, so we
// fake it by setting it to MaxUint64 for basics.AssetParams.
lastGlobalFreeze = math.MaxUint64
}
Comment on lines +258 to +263
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looking for feedback here. From what I can gather AccountToAccountData() is only used by dryrun/tealdbg and then used in 2 tests, but I'm not sure how much energy is going into maintaining them?

Essentially there's now a difference between what basics.AccountData and model.Account holds.

  1. We abstract the basics.AssetHolding.LastFreezeChange away in model.AssetHolding after changing the IsFrozen value.
  2. We abstract the basics.AssetParams.LastGlobalFreeze away in model.AssetParams after adding the Frozen boolean value.

Generally this conversion is done in one direction (from basics.AccountData to model.Account), so it didn't seem like a problem. But if using dryrun I'm now lying about the LastGlobalFreeze value, so it would always win regardless of an accounts local Freeze/LastFreezeChange.

var url string
if ca.Params.Url != nil {
url = *ca.Params.Url
Expand All @@ -269,17 +275,18 @@ func AccountToAccountData(a *model.Account) (basics.AccountData, error) {
}

assetParams[basics.AssetIndex(ca.Index)] = basics.AssetParams{
Total: ca.Params.Total,
Decimals: uint32(ca.Params.Decimals),
DefaultFrozen: defaultFrozen,
UnitName: unitName,
AssetName: name,
URL: url,
MetadataHash: metadataHash,
Manager: manager,
Reserve: reserve,
Freeze: freeze,
Clawback: clawback,
Total: ca.Params.Total,
Decimals: uint32(ca.Params.Decimals),
DefaultFrozen: defaultFrozen,
LastGlobalFreeze: lastGlobalFreeze,
UnitName: unitName,
AssetName: name,
URL: url,
MetadataHash: metadataHash,
Manager: manager,
Reserve: reserve,
Freeze: freeze,
Clawback: clawback,
}
}
}
Expand Down Expand Up @@ -488,6 +495,7 @@ func AssetParamsToAsset(creator string, idx basics.AssetIndex, params *basics.As
Total: params.Total,
Decimals: uint64(params.Decimals),
DefaultFrozen: &frozen,
Frozen: omitEmpty(uint64ToBool(params.LastGlobalFreeze)),
Name: omitEmpty(printableUTF8OrEmpty(params.AssetName)),
NameB64: sliceOrNil([]byte(params.AssetName)),
UnitName: omitEmpty(printableUTF8OrEmpty(params.UnitName)),
Expand Down
Loading