You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ERCs/ERC5XX0 draft.md
+41-81Lines changed: 41 additions & 81 deletions
Original file line number
Diff line number
Diff line change
@@ -12,26 +12,21 @@
12
12
This ERC is a contract interface that adds a `scriptURI()` function for locating executable scripts associated with the token.
13
13
14
14
### Motivation
15
-
Often Smart Contract authors want to provide some user functionality to their tokens through client scripts. The idea is made popular with function-rich NFTs. This should be done safely, without opening the user to potential scams. By packaging a URI to official scripts, created by the token minter, within the token itself, users can be sure they are using the correct script.
15
+
Often Smart Contract authors want to provide some user functionality to their tokens through client scripts. The idea is made popular with function-rich NFTs. By packaging a URI to an official script, created by the token minter, within the token itself, users can be sure they are using the correct script.
16
16
17
-
This ERC proposes adding a scriptURI which is a structure containing an array of URIs to external resources, such as in IPFS, GitHub, a cloud provider, etc.
17
+
This ERC proposes adding a `scriptURI` which is a structure containing an array of URIs to external resources, such as in IPFS, GitHub, a cloud provider, etc., which will store the actual script.
18
18
19
-
Each scriptURI semantically contains access information to access a *single* signed script, stored in one or more off-chain locations.
19
+
Each `scriptURI` semantically contains access information to access a *single* signed script, stored in one or more off-chain locations.
20
20
21
-
Concretely each element in the array contains a pair of URIs, one to the script itself, and one to a signature of the script.
21
+
Concretely each element in the array contains a URI to the script itself.
22
22
23
-
The script provides a client-side executable to the hosting token. Examples of such script:
23
+
The script provides a client-side executable to the hosting token. Examples of such a script could be:
24
24
25
25
- A 'miniDapp', which is a cut-down dapp tailored for a single token.
26
-
-a 'TokenScript' which provides [T.I.P.S.](https://tokenscript.org/TIPS.html) from a browser wallet.
27
-
-an extension that is downlandable to the hardware wallet with an extension framework, such as Ledger.
26
+
-A 'TokenScript' which provides [T.I.P.S.](https://tokenscript.org/TIPS.html) from a browser wallet.
27
+
-An extension that is downloadable to the hardware wallet with an extension framework, such as Ledger.
28
28
29
-
It is expected that the return value of scriptURI() is constantly updated to reflect the current latest version, if used. However, there is a way to assert the authenticity of signed client side code without frequently updating the URI. Developers should refer to ERC 5xx1 which detailed a method of asserting code authenticity without relying on an URI. Note that both ERCs can be used together.
30
-
31
-
To achieve this the token minter can use the signing key associated with the token minting and an associated smart contract, to authenticate a script/scriptURI signing key.
32
-
33
-
Similarly, the smart contract signing key can also be used to overwrite the scriptURI signing key, in case it gets compromised or needs to be rolled.
34
-
The scriptURI signing key is then used to authenticate the URI towards the smart contract, along with the script itself towards anyone accessing it.
29
+
It is expected that the return value of `scriptURI` is constantly updated to reflect the current latest version, if used. However, there is a way to assert the authenticity of signed client side code without frequently updating the URI. Developers should refer to ERC 5xx1 which detail a method of asserting code authenticity without relying on an URI. Note that both ERCs can be used together.
35
30
36
31
#### Script location
37
32
@@ -42,57 +37,40 @@ While the simplest solutions to facilitate specific script usage associated with
42
37
43
38
For these reasons it makes sense to store volatile data, such as token enhancing functionality, on an external resource. Such an external resource can be either centralized, such as a cloud provider or private server, or decentralized such as the interplanetary filesystem.
44
39
40
+
Since using centralized storage for a decentralized functionality goes against the ethos of web3, this ERC handle this this by allowing the token provider to store multiple URIs to the script on-chain. The URIs might point to either multiple centralized storage providers or fully decentralized ones, e.g. the IPFS, another blockchain or even on Ethereum itself. It could also be a mix of centralized and decentralized locations.
41
+
42
+
While this ERC does not dictate the format of the stored script, it should be noted that the script itself could contain pointers to multiple other scripts and data sources. Hence this allows for advanced and rich expansion of tokens.
43
+
44
+
45
45
#### Authenticity
46
46
47
-
If the ScriptURI points to a hash, such as with IPFS, the client (wallet) should assume it authentic, if the hash matches. However, if ScriptURI points to a dynamically downloaded location, the client must verify the signature of the script in the method described ERC xxxx, and warn user against executing the script.
47
+
For validation of authenticity we consider two different cases:
48
48
49
-
Since using centralized storage for a decentralized functionality goes against the ethos of web3, this ERC handle this this by allowing the token provider to store multiple URIs to the script on-chain. The URIs might point to either multiple centralized storage providers or fully decentralized ones, e.g. the IPFS, another blockchain or even on Ethereum itself. It could also be a mix of centralized and decentralized locations.
49
+
1. The `scriptURI` points to decentralized immutable locations *or* the location itself contains information that can validate the authenticity of the script. For example, if the URI points to a location on a blockchain or if the latter part of the URI is a hash digest of the resource it points to, such as with IPFS. In the first situation the client (wallet) should assume it is authentic. In the latter, it case, the client must also validate that the hash describing the location also matches the hash of the script, though.
50
+
51
+
2. If the `scriptURI` points to a dynamic location, the client must verify that the script downloaded has actually been issued by the same entity, which issued the token it is enhancing. The client must also warn the user against execution if this is not the case. However, this scenario is not covered by this ERC, but is handled by ERC 5XX1.
50
52
51
-
While this ERC does not dictate the format of the stored script, it should be noted that the script itself could contain pointers to multiple other scripts and data sources. Hence this allows for advanced and rich expansion of tokens.
52
53
53
54
#### Script updates
54
55
Besides issues of script location, another issue is how the script can be updated in a manner where the caller can be sure it is authentic.
55
-
In this ERC we solve this issue by allowing the issuer to sign and update, on-chain, a scriptURI signing key which can be used to authenticate the script pointed to by the on-chain URI *without* requiring interaction with the smart contract.
56
-
This approach has multiple advantages:
57
-
1. It allows for off-chain updates of the script (as long as the URI does not change), in a way that can be verified by anyone off-chain.
58
-
2. It provides a key management functionality, where the smart contract signing key is not required to make updates to the script or its resources. This in turn, provides a key rolling mechanism and implicitly a revocation mechanism in case the script-signing key ever gets compromised.
59
-
60
-
It is worth noting that if IPFS is used as URI, then updating the script will also result in an updated URI. This requires interaction with the smart contract. However, this can be done without requiring usage of the smart contract signing key, using a public interface method that allows anyone to update the URIs, but _only_ if they sign the parameters (i.e. new URIs) using the scriptURI signing key.
61
-
This ensures that even if IPFS is used and URIs need to be updated every time the script is updates, we can still get the key management advantages of using a script signing key.
56
+
We solve this issue by allowing the issuer to update the `scriptURI` on-chain, when the URI points to an immutable location or the URI itself contains info for script validation.
57
+
This ensures that the script can be changed, even in cases where the URI points to a location based on the hash digest of the script (which is the case if it is stored on the IPFS).
58
+
If instead the `scriptURI` points to a mutable location, it can be updated without on-chain interaction, as described in ERC 5XX1.
62
59
63
60
#### Overview
64
61
65
-
With the discussion above in mind we outline the solution proposed by the ERC. For this purpose we consider the following variables:
62
+
With the discussion above in mind we outline the solution proposed by this ERC. For this purpose we consider the following variables:
66
63
-`SCPrivKey`: The private signing key controlling a smart contract implementing this ERC, which is associated with the tokens issued.
67
-
-`scriptPrivKey`: A private signing key which is used to sign the script issued by the smart contract owner/token provider along with the scriptURI.
68
-
-`scriptKeyAddr`: The address of the public key associated with `scriptPrivKey`, which is used to verify signatures signed with `scriptPrivKey`.
69
64
-`script`: The script supplying additional functionality to the tokens.
70
-
-`sigScript`: The signature on `script` after signing it with `scriptPrivKey`.
71
65
72
-
With these variables in mind we can describe the life cycle of tokens script functionality.
66
+
With these variables in mind we can describe the life cycle of the `scriptURI` functionality:
73
67
- Issuance
74
-
1. The token issuer issues the tokens and a smart contract implementing this ERC, with the controlling key for the smart contract being `SCPrivKey`.
75
-
2. The token issuer samples a `scriptPrivKey` and associated `scriptKeyAddr`. They then sign `script`, to get a signature `sigScript` and stores both at one or more URIs, which are consolidated to a scriptURI.
76
-
3. The token issuer calls `setVerificationKey(scriptKeyAddr)` on the smart contract to set the initial scriptURI signing key.
77
-
4. The token issuer signs the scriptURI with the signing key `scriptPrivKey`. Denote the signature `sigScriptURI`.
78
-
4. The token issuer calls `setScriptURI` with the scriptURI, along with `sigScriptURI`.
79
-
80
-
- Update script
81
-
1. The token issuer signs a new script `script2` using `scriptPrivKey` to get a signature `sigScript2`.
82
-
2. The token issuer updates `script` and `sigScript` at all its URI locations with `script2` and `sigScript2`.
83
-
3. Replace `script` with `script2` and `sigScript` with `sigScript2`.
84
-
85
-
- Update script signing key
86
-
1. The token issuer samples a new script signing key pair denoted `scriptPrivKey2` for the private part and `scriptKeyAddr2` for the public part.
87
-
2. The token issuer signs `script` using `scriptPrivKey2` to get `sigScript2` and then replaces `sigScript` with `sigScript2` at all its URI locations.
88
-
3. The token issuer calls `setVerificationKey(scriptKeyAddr2)`.
89
-
4. Replace `scriptPrivKey` with `scriptPrivKey2`, `scriptKeyAddr` with `scriptKeyAddr2` and `sigScript` with `sigScript2`.
90
-
91
-
- Update script URI
92
-
1. The token issuer moves `script` and `sigScript` from their current URI locations to all new relevant URI locations, and based on this constructs a new scriptURI structure.
93
-
2. The token issuer signs the new scriptURI structure with the signing key `scriptPrivKey`. Denote the signature `sigScriptURI2`.
94
-
3. The token issuer calls `setScriptURI` with the new scriptURI structure, along with `signScriptURI2`.
95
-
4. Replace `scriptPrivKey` with `scriptPrivKey2`.
68
+
1. The token issuer issues the tokens and a smart contract implementing this ERC, with the controlling signing key for the smart contract being `SCPrivKey`.
69
+
2. The token issuer calls `setScriptURI` with the `scriptURI`.
70
+
71
+
- Update `scriptURI`
72
+
1. The token issuer store the desired `script` at all the new URI locations, and based on this, constructs a new `scriptURI` structure.
73
+
2. The token issuer calls `setScriptURI` with the new `scriptURI` structure.
96
74
97
75
98
76
### Specification
@@ -102,61 +80,43 @@ We define a scriptURI element using the following structs:
102
80
103
81
```
104
82
struct scriptURI {
105
-
scriptURIElement[] scriptURIElements;
106
-
}
107
-
struct scriptURIElement {
108
-
string URIOfScript;
109
-
string URIOfSignature;
83
+
string[] URIOfScript;
110
84
}
111
85
```
112
86
113
87
Based on these elements we define the smart contract interface below:
114
88
```
115
-
interface IERC5XXX {
89
+
interface IERC5XX0 {
116
90
/// @dev This event emits when the scriptURI is updated,
117
91
/// so wallets implementing this interface can update a cached script
function setVerificationKey(address memory newVerificationKey)
141
101
}
142
102
```
143
103
The interface MUST be implemented under the following constraints:
144
104
145
-
- The smart contract implementing `IERC5XXX` MUST store variables`address verificationKey` and`address owner` in its state.
105
+
- The smart contract implementing `IERC5XX0` MUST store variables `address owner` in its state.
146
106
147
-
- The smart contract implementing `IERC5XXX` MUST set `owner=msg.sender` in its constructor.
107
+
- The smart contract implementing `IERC5XX0` MUST set `owner=msg.sender` in its constructor.
148
108
149
-
- The ```ScriptUpdate``` event MUST be emitted when the ```setScriptURI``` function updates the scriptURI.
109
+
- The `ScriptUpdate(...)` event MUST be emitted when the ```setScriptURI``` function updates the `scriptURI`.
150
110
151
-
- The ```VerificationKeyUpdate``` event MUST be emitted when the ```setVerificationKey``` function updates the signing key.
111
+
- The `setScriptURI(...)` function MUST validate that `owner == msg.sender`*before* executing its logic and updating any state.
152
112
153
-
- The ```setVerificationKey``` function MUST update the state `verificationKey` to contain `newVerificationKey` if and only if `owner == msg.sender`.
113
+
- The `setScriptURI(...)` function MUST update its internal state such that `currentScriptURI = newScriptURI`.
154
114
155
-
- The `setScriptURI` function MUST validate that `newSigScriptURI` contains a signature on `newScriptURI`, validated against `verificationKey` stored in its state, *before* executing its logic and updating any state.
115
+
- The `scriptURI()` function MUST return the `currentScriptURI` state.
156
116
157
-
- The ```scriptURI()``` function MAY be implemented as pure or view.
117
+
- The `scriptURI()` function MAY be implemented as pure or view.
158
118
159
-
- Any user of the script learned from scriptURI MUST, validate the script and its signature against `verificationKey` before trusting it.
119
+
- Any user of the script learned from `scriptURI` MUST validate the script is either at an immutable location, its URI contains its hash digest, or that it implements ERC 5XX1.
160
120
161
121
162
122
### Rationale
@@ -168,17 +128,17 @@ This standard is compatible with all Token standards (ERC20, 721, 777, 1155 etc)
168
128
### Examples
169
129
We here go through a couple of examples of where an authenticated script is relevant for adding additional functionality for tokens.
170
130
171
-
1. A Utility NFT is a ticket and the authenticated script is a JavaScript 'minidapp' which asks the user to sign a challenge message that shows ownership of the key controlling the ticket. The dapp would then render the signature as a QR code which can be scanned by a ticketing app, which could then mark the ticket used (offchain perhaps).
131
+
1. A Utility NFT is a ticket and the authenticated script is a JavaScript 'minidapp' which asks the user to sign a challenge message that shows ownership of the key controlling the ticket. The dapp would then render the signature as a QR code which can be scanned by a ticketing app, which could then mark the ticket used (off-chain perhaps).
172
132
173
133
2. Smart Token Labs uses a framework called TokenScript; one element of which is a user interface description for contract interaction.
174
134
Simple example: definition for a 'mint' function. This is a simple verb description similar to a JSON contract ABI definition; where the script gives the verb "Mint" and defines how the contract is called - in this case the contract function name 'mint' and attached value for mint fee. In use: for example a Punks v(x) owner wants to mint another punk, the owner can open their punks in wallet or on supported websites and there will be a 'Mint' verb on the token which when clicked will mint a new Punk without needing to reference the mintFee or connect a wallet etc.
175
135
176
-
3. Smartlock controlling NFT script which defines an HTML view and two verbs "lock" and "unlock". Each verb has a JavaScript control script. When the token is selected, the HTML view would be displayed and an attached JavaScript would fetch a challenge string from the lock controller. When each verb is selected by the user in the hosting app or website, the relevant script attached to the verb would execute, prompting the user to sign the challenge then sending the challenge to the lock controller, which would reply with a pass or fail and execute an action accordingly. This is an offchain example that uses onchain assets for functionality.
136
+
3.A Smartlock controlling NFT script which defines an HTML view and two verbs "lock" and "unlock". Each verb has a JavaScript control script. When the token is selected, the HTML view would be displayed and an attached JavaScript would fetch a challenge string from the lock controller. When each verb is selected by the user in the hosting app or website, the relevant script attached to the verb would execute, prompting the user to sign the challenge then sending the challenge to the lock controller, which would reply with a pass or fail and execute an action accordingly. This is an off-chain example that uses on-chain assets for functionality.
0 commit comments