A standard interface to permit restricted approval in token contracts by defining “scopes” of one or more Token IDs.
Abstract
This interface is designed for use with token contracts that have an “ID” domain, such as ERC-1155 or ERC-721. This enables restricted approval of one or more Token IDs to a specific “scope”. When considering a smart contract managing tokens from multiple different domains, it makes sense to limit approvals to those domains. Scoped approval is a generalization of this idea. Implementors can define scopes as needed.
Sample use cases for scopes:
A company may represent its fleet of vehicles on the blockchain and it could create a scope for each regional office.
Game developers could share an ERC-1155 contract where each developer manages tokens under a specified scope.
Tokens of different value could be split into separate scopes. High-value tokens could be kept in smaller separate scopes while low-value tokens might be kept in a shared scope. Users would approve the entire low-value token scope to a third-party smart contract, exchange, or other application without concern about losing their high-value tokens in the event of a problem.
Motivation
It may be desired to restrict approval in some applications. Restricted approval can prevent losses in cases where users do not audit the contracts they’re approving. No standard API is supplied to manage scopes as this is implementation specific. Some implementations may opt to offer a fixed number of scopes, or assign a specific set of scopes to certain types. Other implementations may open up scope configuration to its users and offer methods to create scopes and assign IDs to them.
Specification
pragmasolidity^0.5.2;/**
Note: The ERC-165 identifier for this interface is 0x30168307.
*/interfaceScopedApproval{/**
@dev MUST emit when approval changes for scope.
*/eventApprovalForScope(addressindexed_owner,addressindexed_operator,bytes32indexed_scope,bool_approved);/**
@dev MUST emit when the token IDs are added to the scope.
By default, IDs are in no scope.
The range is inclusive: _idStart, _idEnd, and all IDs in between have been added to the scope.
_idStart must be lower than or equal to _idEnd.
*/eventIdsAddedToScope(uint256indexed_idStart,uint256indexed_idEnd,bytes32indexed_scope);/**
@dev MUST emit when the token IDs are removed from the scope.
The range is inclusive: _idStart, _idEnd, and all IDs in between have been removed from the scope.
_idStart must be lower than or equal to _idEnd.
*/eventIdsRemovedFromScope(uint256indexed_idStart,uint256indexed_idEnd,bytes32indexed_scope);/** @dev MUST emit when a scope URI is set or changes.
URIs are defined in RFC 3986.
The URI MUST point a JSON file that conforms to the "Scope Metadata JSON Schema".
*/eventScopeURI(string_value,bytes32indexed_scope);/**
@notice Returns the number of scopes that contain _id.
@param _id The token ID
@return The number of scopes containing the ID
*/functionscopeCountForId(uint256_id)publicviewreturns(uint32);/**
@notice Returns a scope that contains _id.
@param _id The token ID
@param _scopeIndex The scope index to query (valid values are 0 to scopeCountForId(_id)-1)
@return The Nth scope containing the ID
*/functionscopeForId(uint256_id,uint32_scopeIndex)publicviewreturns(bytes32);/**
@notice Returns a URI that can be queried to get scope metadata. This URI should return a JSON document containing, at least the scope name and description. Although supplying a URI for every scope is recommended, returning an empty string "" is accepted for scopes without a URI.
@param _scope The queried scope
@return The URI describing this scope.
*/functionscopeUri(bytes32_scope)publicviewreturns(stringmemory);/**
@notice Enable or disable approval for a third party ("operator") to manage the caller's tokens in the specified scope.
@dev MUST emit the ApprovalForScope event on success.
@param _operator Address to add to the set of authorized operators
@param _scope Approval scope (can be identified by calling scopeForId)
@param _approved True if the operator is approved, false to revoke approval
*/functionsetApprovalForScope(address_operator,bytes32_scope,bool_approved)external;/**
@notice Queries the approval status of an operator for a given owner, within the specified scope.
@param _owner The owner of the Tokens
@param _operator Address of authorized operator
@param _scope Scope to test for approval (can be identified by calling scopeForId)
@return True if the operator is approved, false otherwise
*/functionisApprovedForScope(address_owner,address_operator,bytes32_scope)publicviewreturns(bool);}
Scope Metadata JSON Schema
This schema allows for localization. {id} and {locale} should be replaced with the appropriate values by clients.
{"title":"Scope Metadata","type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Identifies the scope in a human-readable way.",},"description":{"type":"string","description":"Describes the scope to allow users to make informed approval decisions.",},"localization":{"type":"object","required":["uri","default","locales"],"properties":{"uri":{"type":"string","description":"The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request."},"default":{"type":"string","description":"The locale of the default data within the base JSON"},"locales":{"type":"array","description":"The list of locales for which data is available. These locales should conform to those defined in the Unicode Common Locale Data Repository (http://cldr.unicode.org/)."}}}}}
Localization
Metadata localization should be standardized to increase presentation uniformity across all languages. As such, a simple overlay method is proposed to enable localization. If the metadata JSON file contains a localization attribute, its content may be used to provide localized values for fields that need it. The localization attribute should be a sub-object with three attributes: uri, default and locales. If the string {locale} exists in any URI, it MUST be replaced with the chosen locale by all client software.
Rationale
The initial design was proposed as an extension to ERC-1155: Discussion Thread - Comment 1. After some discussion: Comment 2 and suggestions by the community to implement this approval mechanism in an external contract Comment 3, it was decided that as an interface standard, this design would allow many different token standards such as ERC-721 and ERC-1155 to implement scoped approvals without forcing the system into all implementations of the tokens.
Metadata JSON
The Scope Metadata JSON Schema was added in order to support human-readable scope names and descriptions in more than one language.