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
We are wanting to remove the current param mechanism from the sdk. Due to our commitment to backwards compatibility, this issue is mostly about adding deprecation warnings when params are used and how to migrate away from them.
Background
Currently we can write a script like this using params:
functionadd(a,b,message){returnfcl.send([fcl.script` pub fun main(): Int { log("${p=>p.msg}") return ${p=>p.a} + ${p=>p.b} } `,fcl.params([fcl.param(a,t.Identity,"a"),fcl.param(b,t.Identity,"b"),fcl.param(message,t.Identity,"msg")])])}add(5,6).then(fcl.decode).then(value=>assert(value===5+6))// true
Originally we were hoping to gracefully transition this into the arguments (which were recently added), thinking that people would only need injection style interop or interaction level arguments, but this line of thought proved to be incorrect. We now understand that what the consumer needs is arguments for user input to scripts and transactions, and being able to dynamically change the script/transaction given some sort of external value that is completely in control of the consumer, all of which we can already do.
Injection style interop (params) is also quite tricky. It is susceptible to injection attacks (where the value escapes the current expression, does its own malicious expression, continues on as if nothing happend), the user is responsible for making sure the cadence is valid. For example: log(${p => p.imAString}) would break because the string isn't wrapped in quotes and would have to be written like: log("${p => p.imAString}"), a subtle but devastating issue if missed.
Also the code example above can be done a couple other ways.
First as arguments (the preferred way) which has the following benefits
not susceptible to inject attacks via input as it is typed, and checked by the Cadence VM
no need for thinking about stuff like "do i need to wrap this in quotes".
functionadd(a,b,message){returnfcl.send([fcl.script` pub fun main(a: Int, b: Int): Int { return a + b } `,fcl.args([fcl.arg(a,t.Int),fcl.arg(b,t.Int),])])}// original assert should still hold true
As standard string interop. This has many of the original issues with params, but it is way less complex, closer to what people understand as standard javascript, and is more obvious that the users are responsible for making sure the values once injected into the cadence is valid. (I think its also easier to read and understand the intent than the params)
functionadd(a,b,message){returnfcl.send([fcl.script` pub fun main(): Int { log("${message}") return ${a} + ${b} } `])}// original assert should still hold true
As a mix of the above.
The case for this one would be where the message is in control of the dapp (consumer) while the user of the dapp is in control of a and b. Pros and Cons of the above two examples also apply to this one.
functionadd(a,b,message){returnfcl.send([fcl.script` pub fun main(a: Int, b: Int): Int { log("${message}") return a + b } `,fcl.args([fcl.arg(a,t.Int),fcl.arg(b,t.Int),])])}
Expected Outcome
Transition documentation
How to migrate from current params to arguments and standard interop
Examples of params vs arguments vs standard interop
Display deprecation notices with transition documentation when
fcl.params is called
When a function is interopped into the template literal ${p => p.a}
Documentation on when to use arguments vs standard interop
when to use arguments
when to user standard interop
Stretch Outcome
Display deprecation notices when a value is accessed on the params object (maybe using a proxy?)
The text was updated successfully, but these errors were encountered:
We are wanting to remove the current param mechanism from the sdk. Due to our commitment to backwards compatibility, this issue is mostly about adding deprecation warnings when params are used and how to migrate away from them.
Background
Currently we can write a script like this using params:
Originally we were hoping to gracefully transition this into the arguments (which were recently added), thinking that people would only need injection style interop or interaction level arguments, but this line of thought proved to be incorrect. We now understand that what the consumer needs is arguments for user input to scripts and transactions, and being able to dynamically change the script/transaction given some sort of external value that is completely in control of the consumer, all of which we can already do.
Injection style interop (params) is also quite tricky. It is susceptible to injection attacks (where the value escapes the current expression, does its own malicious expression, continues on as if nothing happend), the user is responsible for making sure the cadence is valid. For example:
log(${p => p.imAString})
would break because the string isn't wrapped in quotes and would have to be written like:log("${p => p.imAString}")
, a subtle but devastating issue if missed.Also the code example above can be done a couple other ways.
First as arguments (the preferred way) which has the following benefits
As standard string interop. This has many of the original issues with params, but it is way less complex, closer to what people understand as standard javascript, and is more obvious that the users are responsible for making sure the values once injected into the cadence is valid. (I think its also easier to read and understand the intent than the params)
As a mix of the above.
The case for this one would be where the
message
is in control of the dapp (consumer) while the user of the dapp is in control ofa
andb
. Pros and Cons of the above two examples also apply to this one.Expected Outcome
Transition documentation
Display deprecation notices with transition documentation when
fcl.params
is called${p => p.a}
Documentation on when to use arguments vs standard interop
Stretch Outcome
The text was updated successfully, but these errors were encountered: