|
1 | | -# asset_labeling |
| 1 | +# Abel: On-Chain Asset Labeling & Verification Registry |
2 | 2 |
|
3 | | -This starter full stack project has been generated using AlgoKit. See below for default getting started instructions. |
| 3 | +## Overview |
| 4 | + |
| 5 | +Registry contract to provide: |
| 6 | + |
| 7 | +1) on- and off-chain verification status for ASAs |
| 8 | +2) supporting multiple providers/labels, and |
| 9 | +3) bonus: enable efficiently fetching (broader) asset information off-chain (batching via simulate) |
| 10 | + |
| 11 | +Impatient? Jump to [setup](#Setup). |
| 12 | + |
| 13 | +### Objectives |
| 14 | + |
| 15 | +**1) Create a transparent and highly available registry for asset verification labels** |
| 16 | + |
| 17 | +Currently, the Pera Asset Verification system has prevailed in our ecosystem. Moving this on-chain will provide higher availability, convenience and transparency. It will also make verification status available to smart contracts via on-chain contract-to-contract calls. |
| 18 | + |
| 19 | +**2) Enable & encourage new asset labeling providers** |
| 20 | + |
| 21 | +Establishing a straightforward distribution method for asset labeling should reduce the friction for other parties to start providing asset labeling services, either as a public good or for private usage. |
| 22 | + |
| 23 | +**3) Provide methods to perform bulk asset information lookups** |
| 24 | + |
| 25 | +The secondary utility of this contract will be offering read-only calls that can be simulated to fetch multiple assets' information at once, for use in frontends like explorers, defi, etc. |
| 26 | + |
| 27 | +Using this method will allow fetching up to 128 assets' data at a time, resulting in significantly reduced overhead in networking/API requests etc. |
| 28 | + |
| 29 | +As an example, rendering a simple asset transfer transaction in a table row will require at minimum the asset decimals (in order to render the amount) and the unit name (in order to indicate the asset being transferred.) Currently, querying for these two pieces of information requires an asset lookup from algod or indexer. |
| 30 | + |
| 31 | +**4) Open source example** |
| 32 | + |
| 33 | +The general concept of this registry is generalizable to other use cases. Open sourcing this contract with a permissive licence would make it useful for other types of registry deployments, and for educational purposes. |
| 34 | + |
| 35 | +### Concepts |
| 36 | + |
| 37 | +The core service provided is **labeling** of **assets**. |
| 38 | + |
| 39 | +A **label** corresponds to a single label by a verification/labeling provider, e.g. "pv" for "Pera Verified", or "ps" for "Pera Suspicious". |
| 40 | + |
| 41 | +Assets can be assigned multiple labels from different operators. |
| 42 | + |
| 43 | +Role based access controls enforce access privileges to each label. |
| 44 | + |
| 45 | +Roles: Admin, Operators (per label.) |
| 46 | + |
| 47 | +- Admin has admin privileges, can create new labels, and add/remove operators to labels. |
| 48 | +- Operators are given access to a $label: |
| 49 | + - add/remove the label $label to any asset |
| 50 | + - add/remove operators to the $label access group |
| 51 | +- Operators can be assigned to multiple labels |
| 52 | + |
| 53 | +_Note: The concept of a "provider" is not mapped to the contract explicitly. RBAC is applied to labels. Multiple labels under the same provider are treated separately, e.g. "Pera Verified" and "Pera Suspicious" are not linked and have separate "operators" in the RBAC system. The complexity of mapping the "provider" entity to the contract logic does not seem to be a reasonable trade-off at this time._ |
| 54 | + |
| 55 | +## Registry Design |
| 56 | + |
| 57 | +### Global storage |
| 58 | + |
| 59 | +```python |
| 60 | +admin: Address |
| 61 | +``` |
| 62 | + |
| 63 | +### Box storage |
| 64 | + |
| 65 | +(Namespacing by box key length, no prefixes needed at this time) |
| 66 | + |
| 67 | +#### Label Descriptors |
| 68 | + |
| 69 | +```python |
| 70 | +[label_id] -> Struct<label_name,num_labels,num_operators> |
| 71 | + |
| 72 | +e.g. "pv" -> ["Pera Verified",2218,2] |
| 73 | +``` |
| 74 | + |
| 75 | +Label ID: must be exactly 2 bytes |
| 76 | + |
| 77 | +#### Operator <> label access |
| 78 | + |
| 79 | +```python |
| 80 | +[operator pk] -> granted_label_id[] |
| 81 | + |
| 82 | +``` |
| 83 | + |
| 84 | +Operator: 32 bytes pk |
| 85 | + |
| 86 | +#### Asset <> Labels |
| 87 | + |
| 88 | +[asset_ID uint64] -> label_id[] |
| 89 | + |
| 90 | +## Registry Methods |
| 91 | + |
| 92 | +### Admin access |
| 93 | + |
| 94 | +```python |
| 95 | +change_admin(new_admin) |
| 96 | +add_label(label_id, label_name, first_operator) |
| 97 | +remove_label(label_id) |
| 98 | +``` |
| 99 | + |
| 100 | +### Admin & Operator access |
| 101 | + |
| 102 | +```python |
| 103 | +add_label_to_operator(operator, label_id) |
| 104 | +remove_label_to_operator(operator, label_id) |
| 105 | +``` |
| 106 | + |
| 107 | +### Operator access |
| 108 | + |
| 109 | +```python |
| 110 | +add_label_to_asset(asset_id, label_id) |
| 111 | +remove_label_from_asset(asset_id, label_id) |
| 112 | +``` |
| 113 | + |
| 114 | +### Public access / read only / label scope |
| 115 | + |
| 116 | +```python |
| 117 | +get_label(label_id) |
| 118 | + |
| 119 | +get_operator_labels(operator) |
| 120 | + |
| 121 | +has_asset_label(asset_id, label_id) -> Bool |
| 122 | +get_asset_labels(asset_id) -> label_id[] |
| 123 | + |
| 124 | +have_assets_label(asset_ids[], label_id) -> Bool[] |
| 125 | +get_assets_labels(asset_ids[]) -> label_id[][] |
| 126 | +``` |
| 127 | + |
| 128 | +_Note: in methods that operate on multiple assets, inputs are mapped to outputs by offset. In `get_assets_labels`, an asset without labels should map to an empty labels array `[]` in the corresponding offset._ |
| 129 | + |
| 130 | +### Public access / read only / mixed scope |
| 131 | + |
| 132 | +## Data fetcher design |
| 133 | + |
| 134 | +On top of verification labels, this contract will enable efficient off-chain querying of asset data. This enables batch asset lookups that include not only label data, but also core asset data, like unit name. |
| 135 | + |
| 136 | +### Asset Views/Structs |
| 137 | + |
| 138 | +We define 4 asset views that will be returned (or logged) as arc4 structs. |
| 139 | + |
| 140 | +Different use cases may opt to fetch |
| 141 | + |
| 142 | +#### Full (including reserve balance for circulating supply calculations) |
| 143 | + |
| 144 | +- Asset Name - AN 32 |
| 145 | +- Unit Name - UN 8 |
| 146 | +- Total - TOT 8 |
| 147 | +- Decimal - DEC 4 |
| 148 | +- URL 96 |
| 149 | +- Manager - MGR 32 |
| 150 | +- Freeze - FRZ 32 |
| 151 | +- Clawback - CLWB 32 |
| 152 | +- Reserve - 32 |
| 153 | +- Reserve Balance - 8 |
| 154 | +- LABELS 4 (? doublecheck dynamicarray<dynamicbytes> overhead) |
| 155 | + |
| 156 | +_Question: Should this include metadata hash and default frozen? Leaning yes._ |
| 157 | + |
| 158 | +Max assets per simulate: 64 (2 resources per asset: 1x acct, 1x asset) |
| 159 | + |
| 160 | +Max logged: 288 x 64 = 18432 bytes |
| 161 | + |
| 162 | +#### Large |
| 163 | + |
| 164 | +- AN 32 |
| 165 | +- UN 8 |
| 166 | +- TOT 8 |
| 167 | +- DEC 4 |
| 168 | +- URL 96 |
| 169 | +- MGR 32 |
| 170 | +- FRZ 32 |
| 171 | +- CLWB 32 |
| 172 | +- RSVR 32 |
| 173 | +- LABELS 4 |
| 174 | + |
| 175 | +(See "full" view for acronym definitions) |
| 176 | + |
| 177 | +max assets per simulate: 128 |
| 178 | + |
| 179 | += 280 x 128 = 35840 max |
| 180 | + |
| 181 | +#### Small |
| 182 | + |
| 183 | +- AN 32 |
| 184 | +- UN 8 |
| 185 | +- TOT 8 |
| 186 | +- DEC 4 |
| 187 | +- URL 96 |
| 188 | +- FRZ_BOOL 1 |
| 189 | +- CLWB_BOOL 1 |
| 190 | +- LABELS 4 |
| 191 | + |
| 192 | +(See "full" view for acronym definitions) |
| 193 | + |
| 194 | +max assets per simulate: 128 |
| 195 | + |
| 196 | += 154 x 128 = 19712 max |
| 197 | + |
| 198 | +#### Tiny |
| 199 | + |
| 200 | +- UN 8 |
| 201 | +- DEC 8 |
| 202 | +- LABELS 4 |
| 203 | + |
| 204 | +(See "full" view for acronym definitions) |
| 205 | + |
| 206 | +max assets per simulate: 128 |
| 207 | + |
| 208 | += 20 x 128 = 2560 max |
| 209 | + |
| 210 | +## View methods |
| 211 | + |
| 212 | +Each view above would have three corresponding read methods. E.g. for the full view: |
| 213 | + |
| 214 | +```python |
| 215 | +get_asset_full(asset_id) -> AssetFullView |
| 216 | +get_assets_full(asset_ids[]) -> AssetFullView[] |
| 217 | +log_assets_full(asset_ids[]) -> void |
| 218 | +``` |
| 219 | + |
| 220 | +The `log_` variants will log each asset view independently. This will allow for more than 4KB of data to be "returned" per simulate request. |
| 221 | + |
| 222 | +**Note: the `get_` variants will fail if the size of the returned data (including arc4 encoding overhead) exceeds 4KB. The `log_` variants should be preferred by the SDK and other clients.** |
| 223 | + |
| 224 | +The full list of methods (4 views x 3 methods) are: |
| 225 | + |
| 226 | +```python |
| 227 | +get_asset_full(asset_id) -> AssetFullView |
| 228 | +get_assets_full(asset_ids[]) -> AssetFullView[] |
| 229 | +log_assets_full(asset_ids[]) -> void |
| 230 | + |
| 231 | +get_asset_large(asset_id) -> AssetLargeView |
| 232 | +get_assets_large(asset_ids[]) -> AssetLargeView[] |
| 233 | +log_assets_large(asset_ids[]) -> void |
| 234 | + |
| 235 | +get_asset_small(asset_id) -> AssetSmallView |
| 236 | +get_assets_small(asset_ids[]) -> AssetSmallView[] |
| 237 | +log_assets_small(asset_ids[]) -> void |
| 238 | + |
| 239 | +get_asset_tiny(asset_id) -> AssetTinyView |
| 240 | +get_assets_tiny(asset_ids[]) -> AssetTinyView[] |
| 241 | +log_assets_tiny(asset_ids[]) -> void |
| 242 | +``` |
| 243 | + |
| 244 | +_Question: should the single asset getter be omitted? the plural variant could be used to fetch a single asset as well. Leaning yes._ |
4 | 245 |
|
5 | 246 | ## Setup |
6 | 247 |
|
|
0 commit comments