Transaction
65360F8D83EA3D…D9E960CA7A43
Block 77,242 · index 1 · indexed
Summary
- Hash
- 65360F8D83EA3DDB4DEB2D3DF68F4C43C954F7EFD5CF5FCEA3C6D9E960CA7A43
- Block
- 77,242
- Size
- 30897 bytes
- Gas used
- 44,600,668 / 53,520,766
- Fee
- 53521ugnot
- Status
- success
Messages
- Package
- gno.land/p/gnoswap/store/v1
Arguments · 15
- #1store
- #2doc.gno
- #3// Package store provides a domain-specific key-value storage system with // permission-based write access control for Gno smart contracts. // // ## Overview // // Each domain (e.g., pool, position, router, staker) creates its own KVStore // instance bound to a unique domain address. That domain address is the // primary authority over the store: it can write, manage the authorized-writer // set, and is itself implicitly authorized as a writer. // // Key components of this package: // // 1. **KVStore Interface** - The contract for domain-specific storage operations. // 2. **kvStore Implementation** - Concrete implementation with permission // management and data storage. // 3. **Write-only Permission System** - Reads are public within the package; // only writes (Set, Delete, ACL changes) are gated. // 4. **Type-Safe Getters** - Typed getter methods with runtime type casting // and validation. // // ## Key Features // // - **Domain Isolation**: Each domain has its own isolated storage space // identified by its domain address. Keys are internally prefixed with that // address so domains cannot collide. // - **Per-Realm Write ACL**: The store maintains an explicit set of realms // authorized to write. The domain owner is in the set by default. // - **Type-Safe Operations**: Specialized getters (`GetInt64`, `GetString`, // `GetAddress`, ...) with automatic casting and structured errors. // - **Realm-Frame Auth Checks**: Every write call accepts a `realm` value // representing the live crossing frame; the store verifies that frame // before consulting the ACL, defending against replayed or captured // `realm` values. // - **Authorized Caller Management**: Dynamic addition, update, and removal // of authorized callers with specific permissions. // // ## Permission Model // // The package defines one assignable permission level: // // - **Write (1)**: Allowed to call `Set` and `Delete`. // // The zero value of `Permission` is reserved and rejected by registration APIs. // Code callers not in the authorized-caller table have no write access. Current // user/EOA realms bypass the ACL for Set and Delete after the live-frame check. // Read methods do not enforce caller permissions; realm-level APIs must gate // sensitive reads themselves. The domain address (owner) is always treated as // authorized and cannot be removed. // // ## Realm Threading // // Every mutating method takes two leading parameters: // // func (k *kvStore) Set(_ int, rlm realm, key string, value any) error // // The leading `_ int` is a deliberate sentinel: at the call site it shows up // as a `0`, making it visually obvious that a `realm` value is being threaded // through. `rlm` is the live crossing frame, and `rlm.IsCurrent()` is checked // first in every mutating method to reject stale or spoofed tokens. // // The v1 -> v2 mapping for the two realm-identity expressions is straightforward: // // - `runtime.CurrentRealm().Address()` -> `rlm.Address()` (the current realm) // - `runtime.PreviousRealm().Address()` -> `rlm.Previous().Address()` (the caller) // // Which one a given method checks is a per-method domain decision, not a v2 // framework rule. The store currently checks: // // - `Set` / `Delete`: `rlm.Address()` (the realm performing the write, i.e. // the domain realm calling into the store) against the write ACL for code // callers. Current user/EOA realms (`!rlm.IsCode()`) bypass the ACL after // `rlm.IsCurrent()` validation, so they can populate or delete state. // - `AddAuthorizedCaller`, `UpdateAuthorizedCaller`, // `RemoveAuthorizedCaller`: `rlm.Address()` (the current realm) against // the domain address. // // ## Workflow // // 1. **Initialization**: Create a store with `NewKVStore(domainAddress)`. // 2. **Data Operations**: Use `Set` / `Get` (and typed getters) for I/O. // 3. **Permission Management**: From the domain realm, call // `AddAuthorizedCaller` to grant write access to additional realms. // 4. **Type-Safe Retrieval**: Prefer typed getters (`GetInt64`, `GetString`, // etc.) over raw `Get` whenever the stored type is known. // // ## Example Usage // // ```gno // package examplerealm // // import ( // // "gno.land/p/gnoswap/store/v1" // // ) // // func Configure(cur realm, routerAddr address) error { // // Create a KVStore owned by the current (pool) realm. // kv := store.NewKVStore(cur.Address()) // // // Persist some values. `0, cur` threads the live realm frame through. // if err := kv.Set(0, cur, "totalLiquidity", uint64(1_000_000)); err != nil { // return err // } // if err := kv.Set(0, cur, "poolName", "ETH-USDC"); err != nil { // return err // } // // // Grant write access to the router realm. // if err := kv.AddAuthorizedCaller(0, cur, routerAddr, store.Write); err != nil { // return err // } // // // Reads are public -- no realm needed. // liquidity, err := kv.GetUint64("totalLiquidity") // if err != nil { // return err // } // _ = liquidity // // return nil // } // // ``` // // ## Permission Checks at a Glance // // The store automatically verifies permissions during operations: // // - **Read Operations** (`Get`, `GetInt64`, `GetString`, ...): no permission // check; reads are public within the package. // - **Write Operations** (`Set`, `Delete`): require the calling realm -- // `rlm.Address()` -- to be in the write ACL when the caller is code. // Current user/EOA realms (`!rlm.IsCode()`) bypass the ACL after the live // frame check. // - **Management Operations** (`AddAuthorizedCaller`, // `UpdateAuthorizedCaller`, `RemoveAuthorizedCaller`): require the // current realm -- `rlm.Address()` -- to equal the domain address. // // ## Key Prefixing // // Internally, all keys are prefixed with the domain address to keep domains // isolated: // // Stored key: "{domainAddress}:{userKey}" // // This prevents key collisions between domains that share a runtime. // // ## Errors // // The package defines several error types: // // - `ErrWritePermissionDenied` - the calling code realm (`rlm.Address()`) is // not in the write ACL. Current user/EOA realms bypass the ACL for Set and // Delete after `rlm.IsCurrent()` validation. // - `ErrUpdatePermissionDenied` - ACL change attempted from a current realm // (`rlm.Address()`) other than the domain address. // - `ErrAuthorizedCallerAlreadyRegistered` - Adding a caller that already // exists. // - `ErrAuthorizedCallerNotFound` - Updating or removing a caller that was // never registered. // - `ErrInvalidPermission` - Permission value other than `Write` was passed. // - `ErrFailedCast` - Typed getter saw a value whose runtime type does not // match. // - `ErrSpoofedRealm` - The supplied `realm` is not the live crossing frame. // // ## Limitations and Considerations // // - All stored values are of type `any`, so retrieval requires either a // typed getter or a cast. // - Read methods are not permission-gated. Add realm-level checks for // sensitive reads. // - ACL management can only be performed by the domain realm itself. // - The domain address is implicitly authorized and cannot be removed. // - Keys are automatically prefixed; callers should not encode the domain // address into their own keys. // // Package store is intended for use in Gno smart contracts that need // isolated, write-gated storage for distinct protocol components. package store
- #4errors.gno
- #5package store const ( // Authorization errors ErrAuthorizedCallerAlreadyRegistered = "authorized caller already registered" ErrAuthorizedCallerNotFound = "authorized caller not found" ErrInvalidPermission = "invalid permission" // Data access errors ErrKeyNotFound = "key not found" ErrWritePermissionDenied = "write permission denied" ErrUpdatePermissionDenied = "update permission denied" ErrFailedCast = "failed to cast" ErrSpoofedRealm = "rlm does not match the current crossing frame" )
- #6gnomod.toml
- #7module = "gno.land/p/gnoswap/store/v1" gno = "0.9"
- #8kv_store.gno
- #9package store import ( "errors" bptree "gno.land/p/nt/bptree/v0" ) // kvStore represents a domain-specific key-value storage // Each domain (pool, position, etc.) creates its own kvStore instance type kvStore struct { data map[string]any // key -> value authorizedCallers map[address]Permission domainAddress address } // NewKVStore creates a new kvStore instance for a specific domain. // domainAddress is the address of the domain realm that owns this store. // // Parameters: // - domainAddress: Address of the owning domain realm; it is initially granted Write permission. // // Returns: // - KVStore: Empty domain-isolated store whose ACL initially authorizes domainAddress for writes. func NewKVStore(domainAddress address) KVStore { return &kvStore{ data: make(map[string]any), authorizedCallers: map[address]Permission{ domainAddress: Write, }, domainAddress: domainAddress, } } // GetDomainAddress returns the domain address. // // Returns: // - address: Address of the domain realm that owns this store. func (k *kvStore) GetDomainAddress() address { return k.domainAddress } // GetAllKeys returns all keys stored in this kvStore. // // Returns: // - []string: Stored keys including the domain-address namespace prefix; map iteration order is unspecified. // - error: Always nil for this in-memory implementation. func (k *kvStore) GetAllKeys() ([]string, error) { keys := make([]string, 0, len(k.data)) // Keys are namespace-prefixed (domainAddress:key) by design for key := range k.data { keys = append(keys, key) } return keys, nil } // Has checks if a key exists in the store. // // Parameters: // - key: Logical key to check; the store applies its domain namespace prefix before lookup. // // Returns: // - bool: true when the namespaced key is present, including when its stored value is nil; false otherwise. func (k *kvStore) Has(key string) bool { _, exists := k.data[k.makeKey(key)] return exists } // Get retrieves a value by key. // Reads are public within the package; only writes are gated by the ACL. // Realms exposing sensitive values must enforce their own read policy before // calling into the store. // // Parameters: // - key: Logical key whose namespaced entry should be retrieved. // // Returns: // - any: Stored value, including an explicitly stored nil, or nil when key is absent. // - error: nil when key exists; otherwise ErrKeyNotFound. func (k *kvStore) Get(key string) (any, error) { value, exists := k.data[k.makeKey(key)] if !exists { return nil, errors.New(ErrKeyNotFound) } return value, nil } // GetInt64 retrieves a value by key and casts it to int64. // Returns ErrFailedCast if the value is not of type int64. // // Parameters: // - key: Logical key whose stored value must have dynamic type int64. // // Returns: // - int64: Stored int64 value, or 0 when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetInt64(key string) (int64, error) { result, err := k.Get(key) if err != nil { return 0, err } return castToInt64(result) } // GetUint64 retrieves a value by key and casts it to uint64. // Returns ErrFailedCast if the value is not of type uint64. // // Parameters: // - key: Logical key whose stored value must have dynamic type uint64. // // Returns: // - uint64: Stored uint64 value, or 0 when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetUint64(key string) (uint64, error) { result, err := k.Get(key) if err != nil { return 0, err } return castToUint64(result) } // GetBool retrieves a value by key and casts it to bool. // Returns ErrFailedCast if the value is not of type bool. // // Parameters: // - key: Logical key whose stored value must have dynamic type bool. // // Returns: // - bool: Stored bool value, or false when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetBool(key string) (bool, error) { result, err := k.Get(key) if err != nil { return false, err } return castToBool(result) } // GetString retrieves a value by key and casts it to string. // Returns ErrFailedCast if the value is not of type string. // // Parameters: // - key: Logical key whose stored value must have dynamic type string. // // Returns: // - string: Stored string value, or the empty string when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetString(key string) (string, error) { result, err := k.Get(key) if err != nil { return "", err } return castToString(result) } // GetAddress retrieves a value by key and casts it to address. // Returns ErrFailedCast if the value is not of type address. // // Parameters: // - key: Logical key whose stored value must have dynamic type address. // // Returns: // - address: Stored address value, or the empty address when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetAddress(key string) (address, error) { result, err := k.Get(key) if err != nil { return address(""), err } return castToAddress(result) } // GetBPTree retrieves a value by key and casts it to *bptree.BPTree. // Returns ErrFailedCast if the value is not of type *bptree.BPTree. // // Parameters: // - key: Logical key whose stored value must have dynamic type *bptree.BPTree. // // Returns: // - *bptree.BPTree: Stored B+ tree pointer, or nil when the key is absent or has another type. // - error: nil on success; otherwise ErrKeyNotFound or ErrFailedCast. func (k *kvStore) GetBPTree(key string) (*bptree.BPTree, error) { result, err := k.Get(key) if err != nil { return nil, err } return castToBPTree(result) } // Set stores a value with the given key. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; this implementation validates rlm.IsCurrent() and uses rlm.Address() for code-caller write authorization. // - key: Logical key under which value is stored; the store adds its domain namespace prefix. // - value: Arbitrary value to store under key. // // Returns: // - error: nil when value is stored; otherwise ErrSpoofedRealm or ErrWritePermissionDenied. func (k *kvStore) Set(_ int, rlm realm, key string, value any) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if rlm.IsCode() && !k.IsWriteAuthorized(rlm.Address()) { return errors.New(ErrWritePermissionDenied) } k.data[k.makeKey(key)] = value return nil } // Delete removes a key from the store. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; this implementation validates rlm.IsCurrent() and uses rlm.Address() for code-caller write authorization. // - key: Logical key whose namespaced entry should be removed. // // Returns: // - error: nil when key is removed; otherwise ErrSpoofedRealm, ErrWritePermissionDenied, or ErrKeyNotFound. func (k *kvStore) Delete(_ int, rlm realm, key string) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if rlm.IsCode() && !k.IsWriteAuthorized(rlm.Address()) { return errors.New(ErrWritePermissionDenied) } if !k.Has(key) { return errors.New(ErrKeyNotFound) } delete(k.data, k.makeKey(key)) return nil } // IsDomainAddress checks if the given address is the domain address. // // Parameters: // - addr: Address to compare with the store's owning domain address. // // Returns: // - bool: true when addr equals the owning domain address; false otherwise. func (k *kvStore) IsDomainAddress(addr address) bool { return k.domainAddress == addr } // IsWriteAuthorized checks if the caller has write permission. // // Parameters: // - caller: Address whose write permission should be evaluated. // // Returns: // - bool: true for the domain address or a registered caller with Write permission; false otherwise. func (k *kvStore) IsWriteAuthorized(caller address) bool { if k.IsDomainAddress(caller) { return true } if !k.isRegisteredAuthorizedCaller(caller) { return false } return k.authorizedCallers[caller] >= Write } // GetAuthorizedCallers returns a copy of the authorized callers map with their permissions. // A copy is returned so callers cannot mutate the ACL map directly. // // Returns: // - map[address]Permission: Newly allocated snapshot of registered caller permissions. // - error: nil when the ACL map exists; otherwise ErrAuthorizedCallerNotFound. func (k *kvStore) GetAuthorizedCallers() (map[address]Permission, error) { if k.authorizedCallers == nil { return make(map[address]Permission), errors.New(ErrAuthorizedCallerNotFound) } out := make(map[address]Permission, len(k.authorizedCallers)) for addr, perm := range k.authorizedCallers { out[addr] = perm } return out, nil } // AddAuthorizedCaller adds a new authorized caller with the specified permission. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; this implementation validates rlm.IsCurrent() and requires its address to be the owning domain for ACL updates. // - caller: Address to add to the write-authorization map. // - permission: Permission to assign; registration APIs accept only Write. // // Returns: // - error: nil when caller is added; otherwise ErrSpoofedRealm, ErrUpdatePermissionDenied, ErrAuthorizedCallerAlreadyRegistered, or ErrInvalidPermission. func (k *kvStore) AddAuthorizedCaller(_ int, rlm realm, caller address, permission Permission) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if !k.isUpdatableAuthorizedCaller(rlm.Address()) { return errors.New(ErrUpdatePermissionDenied) } if k.isRegisteredAuthorizedCaller(caller) { return errors.New(ErrAuthorizedCallerAlreadyRegistered) } if !isValidPermission(permission) { return errors.New(ErrInvalidPermission) } k.authorizedCallers[caller] = permission return nil } // UpdateAuthorizedCaller updates the permission of an existing authorized caller. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; this implementation validates rlm.IsCurrent() and requires its address to be the owning domain for ACL updates. // - caller: Address of the already registered caller whose permission should change. // - permission: Replacement permission; registration APIs accept only Write. // // Returns: // - error: nil when caller's permission is updated; otherwise ErrSpoofedRealm, ErrUpdatePermissionDenied, ErrAuthorizedCallerNotFound, or ErrInvalidPermission. func (k *kvStore) UpdateAuthorizedCaller(_ int, rlm realm, caller address, permission Permission) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if !k.isUpdatableAuthorizedCaller(rlm.Address()) { return errors.New(ErrUpdatePermissionDenied) } if !k.isRegisteredAuthorizedCaller(caller) { return errors.New(ErrAuthorizedCallerNotFound) } if !isValidPermission(permission) { return errors.New(ErrInvalidPermission) } k.authorizedCallers[caller] = permission return nil } // RemoveAuthorizedCaller removes an authorized caller. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; this implementation validates rlm.IsCurrent() and requires its address to be the owning domain for ACL updates. // - caller: Address of the registered caller to remove. // // Returns: // - error: nil when caller is removed; otherwise ErrSpoofedRealm, ErrUpdatePermissionDenied, or ErrAuthorizedCallerNotFound. func (k *kvStore) RemoveAuthorizedCaller(_ int, rlm realm, caller address) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if !k.isUpdatableAuthorizedCaller(rlm.Address()) { return errors.New(ErrUpdatePermissionDenied) } if !k.isRegisteredAuthorizedCaller(caller) { return errors.New(ErrAuthorizedCallerNotFound) } delete(k.authorizedCallers, caller) return nil } // isRegisteredAuthorizedCaller checks if a caller is registered func (k *kvStore) isRegisteredAuthorizedCaller(caller address) bool { _, exists := k.authorizedCallers[caller] return exists } // isUpdatableAuthorizedCaller checks if the current realm is the same as the domain address func (k *kvStore) isUpdatableAuthorizedCaller(currentRealmAddress address) bool { return currentRealmAddress == k.domainAddress } // makeKey creates a prefixed key with the domain address to ensure isolation func (k *kvStore) makeKey(key string) string { return string(k.domainAddress) + ":" + key } // isValidPermission ensures only Write is assignable via registration APIs. // The zero value is rejected so callers must spell out an explicit permission. func isValidPermission(permission Permission) bool { return permission == Write }
- #10types.gno
- #11package store import ( bptree "gno.land/p/nt/bptree/v0" ) type Permission uint8 const ( _ Permission = iota Write ) // KVStore interface for domain-specific storage // Each domain creates its own instance of KVStore type KVStore interface { // GetDomainAddress returns the domain address. // // Returns: // - address: Address of the domain realm that owns this store. GetDomainAddress() address // GetAllKeys returns all keys in this store. // // Returns: // - []string: Keys currently stored by the implementation, including any namespace prefix it uses. // - error: nil when keys are enumerated successfully; otherwise the implementation's retrieval error. GetAllKeys() ([]string, error) // Has checks if a key exists. // // Parameters: // - key: Logical key to test for presence in the store. // // Returns: // - bool: true when key has a stored entry; false when no entry exists. Has(key string) bool // Get retrieves a value by key. // // Parameters: // - key: Logical key whose stored value should be returned. // // Returns: // - any: Value stored under key, including an explicitly stored nil. // - error: nil when key exists; otherwise the implementation's missing-key error. Get(key string) (any, error) // GetInt64 retrieves an int64 value by key. // // Parameters: // - key: Logical key whose value must have dynamic type int64. // // Returns: // - int64: Stored int64 value, or the implementation's zero value when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetInt64(key string) (int64, error) // GetUint64 retrieves a uint64 value by key. // // Parameters: // - key: Logical key whose value must have dynamic type uint64. // // Returns: // - uint64: Stored uint64 value, or the implementation's zero value when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetUint64(key string) (uint64, error) // GetBool retrieves a bool value by key. // // Parameters: // - key: Logical key whose value must have dynamic type bool. // // Returns: // - bool: Stored bool value, or false when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetBool(key string) (bool, error) // GetString retrieves a string value by key. // // Parameters: // - key: Logical key whose value must have dynamic type string. // // Returns: // - string: Stored string value, or the empty string when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetString(key string) (string, error) // GetAddress retrieves an address value by key. // // Parameters: // - key: Logical key whose value must have dynamic type address. // // Returns: // - address: Stored address value, or the empty address when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetAddress(key string) (address, error) // GetBPTree retrieves a B+ tree value by key. // // Parameters: // - key: Logical key whose value must have dynamic type *bptree.BPTree. // // Returns: // - *bptree.BPTree: Stored B+ tree pointer, or nil when retrieval or casting fails. // - error: nil on success; otherwise a missing-key or failed-cast error. GetBPTree(key string) (*bptree.BPTree, error) // Set stores a value with the given key. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; implementations validate it and may use its address for write authorization. // - key: Logical key under which value is stored. // - value: Arbitrary value to associate with key. // // Returns: // - error: nil when value is stored; otherwise the implementation's realm, authorization, or storage error. Set(_ int, rlm realm, key string, value any) error // Delete removes a key. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; implementations validate it and may use its address for write authorization. // - key: Logical key whose stored entry should be removed. // // Returns: // - error: nil when key is removed; otherwise the implementation's realm, authorization, missing-key, or storage error. Delete(_ int, rlm realm, key string) error // IsWriteAuthorized checks if the caller has write permission. // // Parameters: // - caller: Address whose write permission should be checked. // // Returns: // - bool: true when caller is authorized to write; false otherwise. IsWriteAuthorized(caller address) bool // GetAuthorizedCallers returns all authorized callers and their permissions. // // Returns: // - map[address]Permission: Caller-to-permission mapping exposed by the implementation. // - error: nil when the ACL is available; otherwise the implementation's ACL retrieval error. GetAuthorizedCallers() (map[address]Permission, error) // AddAuthorizedCaller adds a new authorized caller. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; implementations validate it before changing ACL state. // - caller: Address to add to the authorization map. // - permission: Permission to assign to caller; the concrete store accepts Write. // // Returns: // - error: nil when caller is added; otherwise the implementation's realm, authorization, duplicate, permission, or storage error. AddAuthorizedCaller(_ int, rlm realm, caller address, permission Permission) error // UpdateAuthorizedCaller updates an existing caller's permission. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; implementations validate it before changing ACL state. // - caller: Address of the registered caller to update. // - permission: Replacement permission for caller; the concrete store accepts Write. // // Returns: // - error: nil when caller's permission is updated; otherwise the implementation's realm, authorization, missing-caller, permission, or storage error. UpdateAuthorizedCaller(_ int, rlm realm, caller address, permission Permission) error // RemoveAuthorizedCaller removes an authorized caller. // // Parameters: // - _: Interrealm-call discriminator; callers pass 0. // - rlm: Propagated current realm context from the domain wrapper; implementations validate it before changing ACL state. // - caller: Address of the registered caller to remove. // // Returns: // - error: nil when caller is removed; otherwise the implementation's realm, authorization, missing-caller, or storage error. RemoveAuthorizedCaller(_ int, rlm realm, caller address) error }
- #12utils.gno
- #13package store import ( bptree "gno.land/p/nt/bptree/v0" ufmt "gno.land/p/nt/ufmt/v0" ) // castToInt64 safely casts an any value to int64 // Returns ErrFailedCast if the value is not of type int64 func castToInt64(result any) (int64, error) { v, ok := result.(int64) if !ok { return 0, ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to int64", result)) } return v, nil } // castToUint64 safely casts an any value to uint64 // Returns ErrFailedCast if the value is not of type uint64 func castToUint64(result any) (uint64, error) { v, ok := result.(uint64) if !ok { return 0, ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to uint64", result)) } return v, nil } // castToBool safely casts an any value to bool // Returns ErrFailedCast if the value is not of type bool func castToBool(result any) (bool, error) { v, ok := result.(bool) if !ok { return false, ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to bool", result)) } return v, nil } // castToString safely casts an any value to string // Returns ErrFailedCast if the value is not of type string func castToString(result any) (string, error) { v, ok := result.(string) if !ok { return "", ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to string", result)) } return v, nil } // castToBPTree safely casts an any value to *bptree.BPTree // Returns ErrFailedCast if the value is not of type *bptree.BPTree func castToBPTree(result any) (*bptree.BPTree, error) { tree, ok := result.(*bptree.BPTree) if !ok { return nil, ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to *bptree.BPTree", result)) } return tree, nil } // castToAddress safely casts an any value to address // Returns ErrFailedCast if the value is not of type address func castToAddress(result any) (address, error) { v, ok := result.(address) if !ok { return address(""), ufmt.Errorf("%s: %s", ErrFailedCast, ufmt.Sprintf("cast %T to address", result)) } return v, nil }
- #14/gno.MemPackageType
- #15 MPUserAll
Result log
msg:0,success:true,log:,events:[]