onflow / cadence Goto Github PK
View Code? Open in Web Editor NEWCadence, the resource-oriented smart contract programming language ๐โโ๏ธ
Home Page: https://developers.flow.com/cadence
License: Apache License 2.0
Cadence, the resource-oriented smart contract programming language ๐โโ๏ธ
Home Page: https://developers.flow.com/cadence
License: Apache License 2.0
Initially we only allowed references to resources, but extended this also to non-resource types. However, the subtyping rules for references only consider composite types. The subtyping rules for non-composite references need to be updated to not only consider composite types, e.g. &Int <: &AnyStruct
.
let x = 1
let xRef = &x as &Int
let anyRef: &AnyStruct = xRef
The current storage interface is low-level: It is key-value based, where keys and values are byte arrays, and the encoding/decoding of Cadence values is implemented in the interpreter. In addition, the interpreter optimizes how an object graph is stored, by decomposing it into multiple key-value pairs.
The current storage optimization to write parts of the object graph to separate storage keys and defer loading them until they are accessed requires knowledge about the kinds of operations that are performed. Currently this optimization is performed for dictionaries, and operations such as getting an value for a key, removing a key, and destroying the dictionary need to perform storage operations.
cadence/runtime/interpreter/value.go
Lines 5616 to 5649 in 4d10cd0
cadence/runtime/interpreter/value.go
Lines 5583 to 5614 in 4d10cd0
cadence/runtime/interpreter/value.go
Lines 5762 to 5802 in 4d10cd0
What type should the storage interface use? Currently the written/read values are of type interpreter.Value
and serialized using a special CBOR encoder and decoder. This could be considered an implementation detail, and the value type intended for external use, cadence.Value
, would be more appropriate. However, this type does not support the deferral optimization. Should it be implemented for cadence.Value
instead? Also, we would need to port the CBOR encoding/decoding to cadence.Value
.
A solution could be to move the value hierarchy interpreter.Value
out of the interpreter
package into a separate package, or even "merge" it with cadence.Value
. This would also reduce the amount of code and maintenance required to support multiple value hierarchies, plus the associated conversion cost.
If a resource or struct has a member function that takes a resource of the same type as an argument, then it should not be able to use itself as an argument.
pub contract Nodes {
pub resource Test {
pub fun deposit(from: @Test) {
destroy from
}
}
init() {
let test <- create Test()
// this line should fail
test.deposit(from: <-test)
}
}
Should invalidate the object that is being invoked so it cannot be used as an argument to itself.
Please fill out the template below to the best of your ability.
Division for UFix64 and Fix64 is not implemented yet.
The error message was not clear to what's wrong within the contract.
Code example:
let result = Fix64(10) / Fix64(2)
Playground Error:
Error: GraphQL error: failed to deploy account code: Execution failed: TODO
Maybe including more info about the function that breaks would help with debugging.
Execution failed: TODO [U]Fix64 division.
(Replace this text:
What are you currently working on that this is blocking?)
Like we now forbid functions to be stored in fields through #62, also prevent certain other types to be stored in fields:
Unlike in #62 for functions, we don't want to remove the subtyping rule.
Contracts may want to verify signatures.
Implement a new Crypto
module which defines:
SignatureAlgorithm
, and constants for the following signature algorithms:
HashAlgorithm
, and constants for the following hash algorithms:
PublicKey
, wich consists of the key data and signature algorithmKeyList
, which allows:
fun add(_ publicKey: PublicKey, hashAlgorithm: HashAlgorithm, weight: UInt32): KeyListEntry
)fun get(keyIndex: Int): KeyListEntry?
)fun revoke(keyIndex: Int)
; entries cannot be deleted)fun isValid(signatureSet: [KeyListSignature], signedData: [UInt8]): Bool
).KeyListEntry
, which has an index (keyIndex
), public key (publicKey
), hash algorithm (hashAlgorithm
), and has a weightKeyListSignature
, which consists of the signature data (signature
), and refers to a key in a key list through a key index (keyIndex
)pub struct interface SignatureVerifier {
pub fun verify(
signature: [UInt8],
tag: String,
signedData: [UInt8],
publicKey: [UInt8],
signatureAlgorithm: String,
hashAlgorithm: String
): Bool
}
pub contract Crypto {
pub struct SignatureAlgorithm {
pub let name: String
init(name: String) {
self.name = name
}
}
// ECDSA_P256 is Elliptic Curve Digital Signature Algorithm (ECDSA) on the NIST P-256 curve
pub let ECDSA_P256: SignatureAlgorithm
// ECDSA_Secp256k1 is Elliptic Curve Digital Signature Algorithm (ECDSA) on the secp256k1 curve
pub let ECDSA_Secp256k1: SignatureAlgorithm
pub struct HashAlgorithm {
pub let name: String
init(name: String) {
self.name = name
}
}
// SHA2_256 is Secure Hashing Algorithm 2 (SHA-2) with a 256-bit digest
pub let SHA2_256: HashAlgorithm
// SHA3_256 is Secure Hashing Algorithm 3 (SHA-3) with a 256-bit digest
pub let SHA3_256: HashAlgorithm
pub struct PublicKey {
pub let publicKey: [UInt8]
pub let signatureAlgorithm: SignatureAlgorithm
init(publicKey: [UInt8], signatureAlgorithm: SignatureAlgorithm) {
self.publicKey = publicKey
self.signatureAlgorithm = signatureAlgorithm
}
}
pub struct KeyListEntry {
pub let keyIndex: Int
pub let publicKey: PublicKey
pub let hashAlgorithm: HashAlgorithm
pub let weight: UFix64
pub let isRevoked: Bool
init(
keyIndex: Int,
publicKey: PublicKey,
hashAlgorithm: HashAlgorithm,
weight: UFix64,
isRevoked: Bool
) {
self.keyIndex = keyIndex
self.publicKey = publicKey
self.hashAlgorithm = hashAlgorithm
self.weight = weight
self.isRevoked = isRevoked
}
}
pub struct KeyList {
priv let entries: [KeyListEntry]
init() {
self.entries = []
}
// Adds a new key with the given weight
pub fun add(
_ publicKey: PublicKey,
hashAlgorithm: HashAlgorithm,
weight: UFix64
): KeyListEntry {
let keyIndex = self.entries.length
let entry = KeyListEntry(
keyIndex: keyIndex,
publicKey: publicKey,
hashAlgorithm: hashAlgorithm,
weight: weight,
isRevoked: false
)
self.entries.append(entry)
return entry
}
// Returns the key at the given index, if it exists.
// Revoked keys are always returned, but they have `isRevoked` field set to true
pub fun get(keyIndex: Int): KeyListEntry? {
if keyIndex >= self.entries.length {
return nil
}
return self.entries[keyIndex]
}
// Marks the key at the given index revoked, but does not delete it
pub fun revoke(keyIndex: Int) {
if keyIndex >= self.entries.length {
return
}
let currentEntry = self.entries[keyIndex]
self.entries[keyIndex] = KeyListEntry(
keyIndex: currentEntry.keyIndex,
publicKey: currentEntry.publicKey,
hashAlgorithm: currentEntry.hashAlgorithm,
weight: currentEntry.weight,
isRevoked: true
)
}
pub fun isValid(
signatureSet: [KeyListSignature],
signedData: [UInt8]
): Bool {
var validWeights: UFix64 = 0.0
let seenKeyIndices: {Int: Bool} = {}
for signature in signatureSet {
// Ensure the key index is valid
if signature.keyIndex >= self.entries.length {
return false
}
// Ensure this key index has not already been seen
if seenKeyIndices[signature.keyIndex] ?? false {
return false
}
// Record the key index was seen
seenKeyIndices[signature.keyIndex] = true
// Get the actual key
let key = self.entries[signature.keyIndex]
// Ensure the key is not revoked
if key.isRevoked {
return false
}
// Ensure the signature is valid
if !Crypto.signatureVerifier.verify(
signature: signature.signature,
tag: Crypto.domainSeparationTagFlowUser,
signedData: signedData,
publicKey: key.publicKey.publicKey,
signatureAlgorithm: key.publicKey.signatureAlgorithm.name,
hashAlgorithm:key.hashAlgorithm.name
) {
return false
}
validWeights = validWeights + key.weight
}
return validWeights >= 1.0
}
}
pub struct KeyListSignature {
pub let keyIndex: Int
pub let signature: [UInt8]
pub init(keyIndex: Int, signature: [UInt8]) {
self.keyIndex = keyIndex
self.signature = signature
}
}
priv let domainSeparationTagFlowUser: String
priv let signatureVerifier: {SignatureVerifier}
init(signatureVerifier: {SignatureVerifier}) {
self.signatureVerifier = signatureVerifier
// Initialize constants
self.ECDSA_P256 = SignatureAlgorithm(name: "ECDSA_P256")
self.ECDSA_Secp256k1 = SignatureAlgorithm(name: "ECDSA_Secp256k1")
self.SHA2_256 = HashAlgorithm(name: "SHA2_256")
self.SHA3_256 = HashAlgorithm(name: "SHA3_256")
self.domainSeparationTagFlowUser = "FLOW-V0.0-user"
}
}
In #169 / #180 we introduced a way to determine if a type can be stored.
The parameter types of script function and transactions must be storable / serializable, so reject script functions and transactions with non-storable parameter types.
When requiring a access(self)
field in a resource in a contract interface, if the resource in the implementation has the same access control modifier, an error is reported. There should be no error.
pub contract interface ContractTypeConform {
pub resource Res {
access(self) var private: Int
}
}
pub contract Example: ContractTypeConform {
pub resource Res {
access(self) var private: Int
init () {
self.private = 0
}
}
}
Res
in Example
does not match the interface according to the static checker.The resource must conform correctly
Making nft storage fields private in an NFT collection
Objects are not being loaded correctly from a dictionary after it has been stored.
go test -v
in the nfttests
directory.missing NFT
SimpleNFT.cdc
. At deployment time, the contract withdraws and deposits token index 1 from the dictionary to make sure that is working. Then in the GenerateDestroyScript
in nft_templates.go
, we load the collection from storage and try to withdraw with causes the missing NFT
error. We had also gotten the error from borrowing a reference to the collection.This test case must pass.
This makes it impossible to withdraw an NFT from a collection, so it blocks testing of the topshot contracts on the testnet
When getting a public capability from an AuthAccount
and comparing it to nil
, the execution panics.
transaction {
prepare(acct: AuthAccount) {
if acct.getCapability(/public/test) == nil {
log("it works")
}
}
}
WARN[3754] โ Transaction reverted txID=fc64e8078cd493038a12372bfb8c2da1aae7b2310cc55a01a75bdb5c400c831d
WARN[3754] ERR [fc64e8] code execution failed: Execution failed:
unreachable
goroutine 206 [running]:
runtime/debug.Stack(0x4dfd0a0, 0x52594c0, 0xc002e203e0)
runtime/debug/stack.go:24 +0x9d
github.com/onflow/cadence/runtime/errors.NewUnreachableError(...)
github.com/onflow/[email protected]/runtime/errors/errors.go:44
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).testEqual(0xc002cb98c0, 0x5258e60, 0xc002e20400, 0x5259940, 0x6f83920, 0xc00361c378)
github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:1730 +0x160
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).VisitBinaryExpression.func16(0x4dd9180, 0xc002e208c0, 0xc002e20980, 0xc00361c3f8)
github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:1632 +0x67
github.com/onflow/cadence/runtime/trampoline.MapTrampoline.func1(0x4dd9180, 0xc002e208c0, 0xc002e205a0, 0x1339a7240524a740)
github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:50 +0x39
github.com/onflow/cadence/runtime/trampoline.FlatMap.FlatMap.func1(0x4dd9180, 0xc002e208c0, 0xc002e208c0, 0xc002e20960)
github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:123 +0x42
github.com/onflow/cadence/runtime/trampoline.FlatMap.FlatMap.func1(0x4dd9180, 0xc002e208c0, 0x4cf7fa0, 0xc002e20980)
github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:123 +0x42
github.com/onflow/cadence/runtime/trampoline.FlatMap.Resume.func1(0xc002e20960, 0x4cf7fa0)
github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:134 +0x37
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).runUntilNextStatement(0xc002cb98c0, 0x524a740, 0xc002e20960, 0x0, 0x0, 0xc002e20600)
github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:585 +0x35
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).runAllStatements(0xc002cb98c0, 0x524a740, 0xc001dfb5a0, 0x1, 0x1)
github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:595 +0x56
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).InvokeTransaction(0xc002cb98c0, 0x0, 0xc00070c1f0, 0x1, 0x1, 0x0, 0x0)
github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:813 +0x137
github.com/onflow/cadence/runtime.(*interpreterRuntime).transactionExecutionFunction.func1(0xc002cb98c0, 0x0, 0x0, 0xc00361c710, 0xc00361c710)
github.com/onflow/[email protected]/runtime/runtime.go:390 +0x575
github.com/onflow/cadence/runtime.(*interpreterRuntime).interpret.func1()
github.com/onflow/[email protected]/runtime/runtime.go:191 +0xa4
github.com/onflow/cadence/runtime.reportMetric(0xc00361c838, 0x5269660, 0xc002c1e0d0, 0xc00361c820)
github.com/onflow/[email protected]/runtime/runtime.go:97 +0xf3
github.com/onflow/cadence/runtime.(*interpreterRuntime).interpret(0x6f83920, 0x522db20, 0xc002146820, 0x5269660, 0xc002c1e0d0, 0xc002146840, 0xc0004c4d00, 0xc000138000, 0x7, 0xa, ...)
github.com/onflow/[email protected]/runtime/runtime.go:185 +0x1d2
github.com/onflow/cadence/runtime.(*interpreterRuntime).ExecuteTransaction(0x6f83920, 0xc000020240, 0xb8, 0xc0, 0x6f83920, 0x0, 0x0, 0x5269660, 0xc002c1e0d0, 0x522db20, ...)
github.com/onflow/[email protected]/runtime/runtime.go:298 +0x57c
github.com/dapperlabs/flow-go/engine/execution/computation/virtualmachine.(*virtualMachine).executeTransaction(...)
github.com/dapperlabs/[email protected]/engine/execution/computation/virtualmachine/virtualMachine.go:68
github.com/dapperlabs/flow-go/engine/execution/computation/virtualmachine.(*blockContext).ExecuteTransaction(0xc001b02cc0, 0x52426c0, 0xc003094540, 0xc0001249c0, 0xc002d5e420, 0x2, 0x2, 0xc003094540, 0x0, 0x6f83920)
github.com/dapperlabs/[email protected]/engine/execution/computation/virtualmachine/blockContext.go:135 +0x24d
github.com/dapperlabs/flow-emulator.(*Blockchain).executeNextTransaction.func1(0xc003094540, 0xc0001249c0, 0xc002b94e20, 0xc003402528, 0x795b008)
github.com/dapperlabs/[email protected]/blockchain.go:586 +0xdd
github.com/dapperlabs/flow-emulator.(*pendingBlock).ExecuteNextTransaction(0xc001437560, 0xc002b95160, 0xc002c926a0, 0x8, 0x40164af)
github.com/dapperlabs/[email protected]/pendingBlock.go:154 +0x10f
github.com/dapperlabs/flow-emulator.(*Blockchain).executeNextTransaction(0xc00038f480, 0x5242680, 0xc001b02cc0, 0xc00038f480, 0x5242680, 0xc001b02cc0)
github.com/dapperlabs/[email protected]/blockchain.go:581 +0xaf
github.com/dapperlabs/flow-emulator.(*Blockchain).executeBlock(0xc00038f480, 0x10, 0xc002b952b8, 0x45eca17, 0x0, 0x0)
github.com/dapperlabs/[email protected]/blockchain.go:548 +0x147
github.com/dapperlabs/flow-emulator.(*Blockchain).executeAndCommitBlock(0xc00038f480, 0xaa32d30b27b4b879, 0x8c19289c8b185885, 0x8693cef1332bb26c, 0x1573fbfa6b0a639f, 0xf93487d7f889e2d1, 0x7899273455a81143)
github.com/dapperlabs/[email protected]/blockchain.go:667 +0x43
github.com/dapperlabs/flow-emulator.(*Blockchain).ExecuteAndCommitBlock(0xc00038f480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
github.com/dapperlabs/[email protected]/blockchain.go:661 +0xa9
github.com/dapperlabs/flow-emulator/server.(*Backend).commitBlock(0xc001bf9a40)
github.com/dapperlabs/[email protected]/server/backend.go:422 +0x4c
github.com/dapperlabs/flow-emulator/server.(*Backend).SendTransaction(0xc001bf9a40, 0x5249a80, 0xc000c95f50, 0xc000c95f80, 0xc001bf9a40, 0x5254f60, 0xc002bf3ec0)
github.com/dapperlabs/[email protected]/server/backend.go:86 +0x8e5
github.com/onflow/flow/protobuf/go/flow/access._AccessAPI_SendTransaction_Handler.func1(0x5249a80, 0xc000c95f50, 0x4e64f20, 0xc000c95f80, 0x21, 0xc002800aa0, 0x0, 0xc002c9dae8)
github.com/onflow/flow/protobuf/go/[email protected]/access/access.pb.go:1800 +0x89
github.com/grpc-ecosystem/go-grpc-prometheus.(*ServerMetrics).UnaryServerInterceptor.func1(0x5249a80, 0xc000c95f50, 0x4e64f20, 0xc000c95f80, 0xc001b028c0, 0xc001b028e0, 0xc002c46b58, 0x410d828, 0x4e54080, 0xc000c95f50)
github.com/grpc-ecosystem/[email protected]/server_metrics.go:107 +0xad
github.com/onflow/flow/protobuf/go/flow/access._AccessAPI_SendTransaction_Handler(0x4ee72c0, 0xc001bf9a40, 0x5249a80, 0xc000c95f50, 0xc004a4a180, 0xc0003e0360, 0x5249a80, 0xc000c95f50, 0xc002966000, 0x150)
github.com/onflow/flow/protobuf/go/[email protected]/access/access.pb.go:1802 +0x14b
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0003e49c0, 0x525ce80, 0xc0004a8480, 0xc0030d0100, 0xc000ac4270, 0x6f54de0, 0x0, 0x0, 0x0)
google.golang.org/[email protected]/server.go:1082 +0x4fd
google.golang.org/grpc.(*Server).handleStream(0xc0003e49c0, 0x525ce80, 0xc0004a8480, 0xc0030d0100, 0x0)
google.golang.org/[email protected]/server.go:1405 +0xd25
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc001b97340, 0xc0003e49c0, 0x525ce80, 0xc0004a8480, 0xc0030d0100)
google.golang.org/[email protected]/server.go:746 +0xbb
created by google.golang.org/grpc.(*Server).serveStreams.func1
google.golang.org/[email protected]/server.go:744 +0xa1
This does not cause an issue when trying to get the capability from storage
No panic
As per the JSON-CDC spec, fixed point numbers do not need to be encoded with trailing zeros after the decimal point: https://github.com/onflow/flow/blob/master/docs/json-cadence-spec.md#fixed-point-numbers
However, the encoding/json
package only correctly decodes JSON-CDC Fix64
and UFix64
values if they contain exactly 8 digits after the decimal point.
For example, this value:
{
"type": "Fix64",
"value": "12.3"
}
is incorrectly decoded as 0.00000123
.
Whereas this value:
{
"type": "Fix64",
"value": "12.30000000"
}
is correctly decoded as 12.3
.
Got a runtime panic when trying to deploy contracts as part of automated tests
Use this branch of the flow-ft repo: https://github.com/onflow/flow-ft/tree/josh/transactions
This uses github.com/onflow/[email protected]
github.com/dapperlabs/[email protected]
github.com/dapperlabs/flow-go@30b3e2d5a5860c437e523921d08a97896b1e50e0
github.com/onflow/[email protected]
Go to lib/go/test/
and run go test -v
See the runtime panic
=== RUN TestTokenDeployment
--- FAIL: TestTokenDeployment (0.33s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x70 pc=0x141a25c]
goroutine 36 [running]:
testing.tRunner.func1.1(0x1936360, 0x24f2d00)
/usr/local/Cellar/go/1.14/libexec/src/testing/testing.go:941 +0x3d0
testing.tRunner.func1(0xc0001ccc60)
/usr/local/Cellar/go/1.14/libexec/src/testing/testing.go:944 +0x3f9
panic(0x1936360, 0x24f2d00)
/usr/local/Cellar/go/1.14/libexec/src/runtime/panic.go:967 +0x15d
github.com/onflow/cadence/runtime/interpreter.recoverErrors(0xc000674710)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:864 +0x15a
panic(0x1936360, 0x24f2d00)
/usr/local/Cellar/go/1.14/libexec/src/runtime/panic.go:967 +0x15d
github.com/onflow/cadence/runtime/sema.(*CapabilityType).Unify(0xc0001930a0, 0x1d12660, 0xc0001930a0, 0xc000910a50, 0xc000541b80, 0x922, 0x42, 0x2d, 0x92a, 0x42, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/type.go:6652 +0x4c
github.com/onflow/cadence/runtime/sema.(*Checker).checkInvocationRequiredArgument(0xc0000d6300, 0xc0000ac2a0, 0x1, 0x1, 0x0, 0xc00057b540, 0xc000541b20, 0x1, 0x1, 0xc000910a50, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_invocation_expression.go:481 +0x28a
github.com/onflow/cadence/runtime/sema.(*Checker).checkInvocation(0xc0000d6300, 0xc0001e24e0, 0x1d15a00, 0xc000541a50, 0xc000541a50, 0x1, 0x0, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_invocation_expression.go:380 +0x27f
github.com/onflow/cadence/runtime/sema.(*Checker).checkInvocationExpression.func3(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_invocation_expression.go:97
github.com/onflow/cadence/runtime/sema.(*Checker).checkInvocationExpression(0xc0000d6300, 0xc0001e24e0, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_invocation_expression.go:107 +0x7af
github.com/onflow/cadence/runtime/sema.(*Checker).VisitInvocationExpression(0xc0000d6300, 0xc0001e24e0, 0xc0000d6300, 0x2f153e8)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_invocation_expression.go:27 +0x3f
github.com/onflow/cadence/runtime/ast.(*InvocationExpression).AcceptExp(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:339
github.com/onflow/cadence/runtime/ast.(*InvocationExpression).Accept(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:335
github.com/onflow/cadence/runtime/sema.(*Checker).VisitCreateExpression(0xc0000d6300, 0xc0002a1280, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_create_expression.go:37 +0xd8
github.com/onflow/cadence/runtime/ast.(*CreateExpression).AcceptExp(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:646
github.com/onflow/cadence/runtime/ast.(*CreateExpression).Accept(0xc0002a1280, 0x1d2e1c0, 0xc0000d6300, 0xc000671458, 0x142aaf9)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:642 +0x5f
github.com/onflow/cadence/runtime/sema.(*Checker).VisitUnaryExpression(0xc0000d6300, 0xc0003a6870, 0xc0000d6300, 0x2f153e8)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_unary_expression.go:28 +0x62
github.com/onflow/cadence/runtime/ast.(*UnaryExpression).AcceptExp(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:507
github.com/onflow/cadence/runtime/ast.(*UnaryExpression).Accept(0xc0003a6870, 0x1d2e1c0, 0xc0000d6300, 0xc000671560, 0x100c1ea)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/expression.go:503 +0x62
github.com/onflow/cadence/runtime/sema.(*Checker).VisitReturnStatement(0xc0000d6300, 0xc0002d7d00, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_return_statement.go:56 +0x292
github.com/onflow/cadence/runtime/ast.(*ReturnStatement).Accept(0xc0002d7d00, 0x1d2e1c0, 0xc0000d6300, 0x1ced901, 0x1ced9a0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/statement.go:36 +0x3e
github.com/onflow/cadence/runtime/sema.(*Checker).visitStatements(0xc0000d6300, 0xc0003142d0, 0x1, 0x1)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_block.go:68 +0x14b
github.com/onflow/cadence/runtime/sema.(*Checker).visitFunctionBlock.func1()
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:350 +0x4b
github.com/onflow/cadence/runtime/sema.(*Checker).visitWithPostConditions(0xc0000d6300, 0x0, 0x1d12760, 0xc0007d72c0, 0xc0006717d8)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:308 +0x54
github.com/onflow/cadence/runtime/sema.(*Checker).visitFunctionBlock(0xc0000d6300, 0xc0002a12c0, 0xc0001729e0, 0x1)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:343 +0xcf
github.com/onflow/cadence/runtime/sema.(*Checker).checkFunction.func2()
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:158 +0x16f
github.com/onflow/cadence/runtime/sema.(*FunctionActivations).WithFunction(0xc0002a1560, 0xc00057b640, 0x3, 0xc000671928)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/function_activations.go:67 +0xfa
github.com/onflow/cadence/runtime/sema.(*Checker).checkFunction(0xc0000d6300, 0xc0004138b0, 0xc0003a6660, 0xc00057b640, 0xc0002a12c0, 0x1, 0x0, 0x1)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:141 +0x17a
github.com/onflow/cadence/runtime/sema.(*Checker).visitFunctionDeclaration(0xc0000d6300, 0xc0001e2540, 0xc000010001, 0x19559c0, 0xc000910900)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_function.go:77 +0x13d
github.com/onflow/cadence/runtime/sema.(*Checker).checkCompositeFunctions.func1(0xc0000d6300, 0xc0007d7180, 0xc000671a90)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_composite_declaration.go:1386 +0xa2
github.com/onflow/cadence/runtime/sema.(*Checker).checkCompositeFunctions(0xc0000d6300, 0xc0000ac2b0, 0x1, 0x1, 0xc0007d7180)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_composite_declaration.go:1394 +0x7d
github.com/onflow/cadence/runtime/sema.(*Checker).visitCompositeDeclaration(0xc0000d6300, 0xc000222780, 0x2)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_composite_declaration.go:115 +0x5ca
github.com/onflow/cadence/runtime/sema.(*Checker).VisitCompositeDeclaration(0xc0000d6300, 0xc000222780, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/check_composite_declaration.go:28 +0x3e
github.com/onflow/cadence/runtime/ast.(*CompositeDeclaration).Accept(0xc000222780, 0x1d2e1c0, 0xc0000d6300, 0x2, 0x1054d3c)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/composite.go:41 +0x3b
github.com/onflow/cadence/runtime/sema.(*Checker).VisitProgram(0xc0000d6300, 0xc0001b8f20, 0x10896c6, 0x5f063b6d)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/checker.go:453 +0x417
github.com/onflow/cadence/runtime/ast.(*Program).Accept(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/ast/program.go:53
github.com/onflow/cadence/runtime/sema.(*Checker).Check.func1()
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/checker.go:326 +0x3b
github.com/onflow/cadence/runtime.(*interpreterRuntime).parseAndCheckProgram.func3.1()
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:524 +0x24
github.com/onflow/cadence/runtime.reportMetric(0xc000673b00, 0x1d1c520, 0xc0000d6800, 0xc000673b10)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:104 +0x93
github.com/onflow/cadence/runtime.(*interpreterRuntime).parseAndCheckProgram.func3(0x1ced640, 0xc0002e1ce0, 0xc000315050)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:522 +0x97
github.com/onflow/cadence/runtime/sema.(*Checker).Check(0xc0000d6300, 0x1ced640, 0xc0002e1ce0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/sema/checker.go:329 +0x128
github.com/onflow/cadence/runtime.(*interpreterRuntime).parseAndCheckProgram(0xc0002499c0, 0xc0003d2a80, 0x935, 0x935, 0x1d1c520, 0xc0000d6800, 0x1ced640, 0xc0002e1ce0, 0xc000146a80, 0x8, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:540 +0x42d
github.com/onflow/cadence/runtime.(*interpreterRuntime).updateAccountCode(0xc0002499c0, 0x1d1c520, 0xc0000d6800, 0xc0004e4720, 0xc0003d2a80, 0x935, 0x935, 0xee5e8fa7c1d2fcf3, 0xc0002c0b90, 0x0, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:1080 +0x181
github.com/onflow/cadence/runtime.(*interpreterRuntime).newSetCodeFunction.func1(0x0, 0xc0002c0b90, 0x1, 0x1, 0xc00007c0c0, 0x1, 0x1, 0xc000410330, 0x1ced620, 0xc0004e4700, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:1032 +0x1fd
github.com/onflow/cadence/runtime/interpreter.HostFunctionValue.Invoke(...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/function.go:155
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).functionValueInvocationTrampoline(0xc0000b5800, 0x1d0cf60, 0xc0002c0400, 0xc0002c0b40, 0x1, 0x1, 0xc00007c0c0, 0x1, 0x1, 0xc00007c0d0, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:2098 +0x311
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).VisitInvocationExpression.func1.1(0x1a1af60, 0xc0000de6c0, 0xc0002e16c0, 0x1339a72401cfeaa0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:2016 +0x2c9
github.com/onflow/cadence/runtime/trampoline.FlatMap.FlatMap.func1(0x1a1af60, 0xc0000de6c0, 0xc0000de6c0, 0xc0002e1c20)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:142 +0x42
github.com/onflow/cadence/runtime/trampoline.FlatMap.FlatMap.func1(0x1a1af60, 0xc0000de6c0, 0x18df080, 0xc0002e1c40)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:142 +0x42
github.com/onflow/cadence/runtime/trampoline.FlatMap.Resume.func1(0xc0002e1c20, 0x18df080)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/trampoline/trampoline.go:154 +0x37
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).runUntilNextStatement(0xc0000b5800, 0x1cfeaa0, 0xc0002e1c20, 0x0, 0x0, 0xc0002e1720)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:608 +0x35
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).runAllStatements(0xc0000b5800, 0x1cfeaa0, 0xc00000e160, 0x3, 0x4)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:620 +0x56
github.com/onflow/cadence/runtime/interpreter.(*Interpreter).InvokeTransaction(0xc0000b5800, 0x0, 0xc00004cec0, 0x3, 0x4, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/interpreter/interpreter.go:853 +0x118
github.com/onflow/cadence/runtime.(*interpreterRuntime).transactionExecutionFunction.func1(0xc0000b5800, 0x0, 0x0, 0x2854a17800472850, 0x5f063b6d)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:400 +0x183
github.com/onflow/cadence/runtime.(*interpreterRuntime).interpret.func1()
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:232 +0xa4
github.com/onflow/cadence/runtime.reportMetric(0xc000472978, 0x1d1c520, 0xc0000d6800, 0xc000674960)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:104 +0x93
github.com/onflow/cadence/runtime.(*interpreterRuntime).interpret(0xc0002499c0, 0x1ced620, 0xc0004e4700, 0x1d1c520, 0xc0000d6800, 0xc0004e4720, 0xc0000d6900, 0xc000146380, 0x8, 0xc, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:226 +0x1d2
github.com/onflow/cadence/runtime.(*interpreterRuntime).ExecuteTransaction(0xc0002499c0, 0xc000654340, 0xce, 0xce, 0xc000715c80, 0x2, 0x2, 0x1d1c520, 0xc0000d6800, 0x1ced620, ...)
/Users/joshuahannan/go/pkg/mod/github.com/onflow/[email protected]/runtime/runtime.go:339 +0x57d
github.com/dapperlabs/flow-go/fvm.(*TransactionInvocator).Process(0x2536258, 0xc000520b30, 0x1d08d40, 0x24f51c0, 0x1cf36e0, 0xc0005241f0, 0x1ced4c0, 0xc0001ccd80, 0x0, 0x186a0, ...)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/fvm/transaction.go:90 +0x272
github.com/dapperlabs/flow-go/fvm.(*TransactionProcedure).Run(0xc000356cb0, 0xc000520b30, 0x1d08d40, 0x24f51c0, 0x1cf36e0, 0xc0005241f0, 0x1ced4c0, 0xc0001ccd80, 0x0, 0x186a0, ...)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/fvm/transaction.go:37 +0xe4
github.com/dapperlabs/flow-go/fvm.(*VirtualMachine).Run(...)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/fvm/fvm.go:29
github.com/dapperlabs/flow-emulator.(*Blockchain).executeNextTransaction.func1(0xc00057ae40, 0xc0000b5a40, 0xc000475230, 0xc0000d8ec8, 0x1000000016681e3)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/blockchain.go:613 +0x1c7
github.com/dapperlabs/flow-emulator.(*pendingBlock).ExecuteNextTransaction(0xc0001110e0, 0xc0004754a8, 0x1ced4c0, 0xc0001ccd80, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/pendingBlock.go:148 +0x10f
github.com/dapperlabs/flow-emulator.(*Blockchain).executeNextTransaction(0xc0001ccd80, 0x1d08d40, 0x24f51c0, 0x1cf36e0, 0xc0005241f0, 0x1ced4c0, 0xc0001ccd80, 0x0, 0x186a0, 0xc000210620, ...)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/blockchain.go:606 +0xa7
github.com/dapperlabs/flow-emulator.(*Blockchain).executeBlock(0xc0001ccd80, 0xce, 0xc000715c80, 0x2, 0x2, 0x3b9ac9ff)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/blockchain.go:570 +0x20e
github.com/dapperlabs/flow-emulator.(*Blockchain).executeAndCommitBlock(0xc0001ccd80, 0xc000654340, 0xce, 0xce, 0xc000715c80, 0x2, 0x2)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/blockchain.go:694 +0x43
github.com/dapperlabs/flow-emulator.(*Blockchain).CreateAccount(0xc0001ccd80, 0xc000475f58, 0x1, 0x1, 0xc0006bca80, 0x935, 0xa80, 0x0, 0x0, 0x0)
/Users/joshuahannan/go/pkg/mod/github.com/dapperlabs/[email protected]/blockchain.go:812 +0x393
github.com/onflow/flow-ft/lib/go/test.DeployTokenContracts(0xc0001ccd80, 0xc0001ccc60, 0xc000475f58, 0x1, 0x1, 0x0, 0x0, 0x0)
/Users/joshuahannan/flow/flow-ft/lib/go/test/token_test.go:433 +0x29e
github.com/onflow/flow-ft/lib/go/test.TestTokenDeployment(0xc0001ccc60)
/Users/joshuahannan/flow/flow-ft/lib/go/test/token_test.go:24 +0xeb
testing.tRunner(0xc0001ccc60, 0x1bd0c80)
/usr/local/Cellar/go/1.14/libexec/src/testing/testing.go:992 +0xdc
created by testing.(*T).Run
/usr/local/Cellar/go/1.14/libexec/src/testing/testing.go:1043 +0x357
exit status 2
There are currently inconsistencies in the way errors are passed from the host environment to the runtime and back (through runtime.Interface
).
Errors can be classified into three categories:
error
valueUser and fatal errors can originate from both the runtime.Interface
implementation (host environment) and from inside the runtime. However, we currently lack a well-defined pattern for differentiating between user errors and fatal errors that originate from the host environment.
With the introduction of the Crypto
built-in package, there is now a use case for converting arbitrary Cadence values into a serialized byte array, which can then be hashed and verified against a signature.
This encoding format should be secure and well-defined, allowing users to encode values in an external environment (i.e. Go, JavaScript) and expect Cadence to produce the same results.
This encoding format may only need to support Cadence value types (i.e. no resources).
Expose an Encoding.RLP
package as part of the Cadence standard library.
RLP.Encode(value: AnyStruct)
)Add a toBytes
method to value types that produces a consistent byte-wise encoding.
let myIntBytes = myInt.toBigEndianBytes()
A way to iterate over the storage to be able to list the resources owned by an account.
for entry in account.storageEntries { log(entry) }
getAccount(โ0x01")
storage
field with data in the cadence format (json with types)If there are multiple solutions, please present each one separately. Save comparisons for the very end.)
Iโm working on a marketplace and I was looking for a way to list all NFTs owned by an account.
New features have been added to Cadence in the last few releases.
Update the documentation and describe the new features
Get the current block:
fun getCurrentBlock(): Block
Get a block at a given height:
fun getBlock(at height: UInt64): Block?
The block info is:
struct Block {
let id: [UInt8; 32]
let height: UInt64
let timestamp: UFix64
}
fun toString(): String
was added for all number types and addressesfun toBytes(): [UInt8]
was added to Address
fun toBigEndianBytes(): [UInt8]
was added to all number types.((Int): Bool)
)AuthAccount
/ PublicAccount
)Void
String.decodeHex(): [Int]
โ String.decodeHex(): [UInt8]
AuthAccount.addPublicKey(publicKey: [Int])
โ AuthAccount.addPublicKey(publicKey: [UInt8])
AuthAccount.setCode(code: [Int])
โ AuthAccount.setCode(code: [UInt8])
unsafeRandom
Some embedders of Cadence, e.g. the Playground, need to get the high-level representation (i.e. cadence.Value
, not low-level byte-encoded representation).
Add an additional callback that gets called in addition to the low-level write callback (SetValue
).
cadence.Value
instead of a []byte
.cc @psiemens
Using interfaces we can't check what type is really used at run-time, sometimes it's required to check a specific type. Need to know the full name of a type I'm working with.
I know you are working to add a new type Type
, so maybe you can add something like fun getType(): Type
and also a fun toString(): String
to the Type
if it doesn't exist now.
I'd expect to call it in the following way: obj.getType().toString()
.
The format of a name of a type can be for instance: T.{account_address}.{contract_name}.{type_name}
The key indices used in the CBOR encoder and decoder can easily get out of sync.
Introduce constants that are used on both sides.
Define constants for the keys in the CBOR encoder, e.g.:
const (
EncodedTypeValueType uint64 = 0
)
type encodedTypeValue struct {
Type interface{} `cbor:"0,keyasint"`
}
Use the key constants in the CBOR decoder, e.g.:
decodedStaticType, err := d.decodeStaticType(encoded[EncodedTypeValueType])
Values that are transferred from a dictionary in one account to another account are not being stored correctly, so that a transaction that tries to access that value in the second dictionary causes the runtime to panic.
Runtime must not panic and value must be accessed correctly
Blocking NFT contracts from working correctly
Currently account code may only declare up to one contract, and multiple contract interfaces.
There is one function, fun AuthAccount.setCode(_ code: [UInt8], ... initializerArguments)
, which updates the account's code,
and (if any) instantiates the contract and stores it in the world state.
The function is used both for initial contract deployment and for contract updates.
For the latter use case, this means that the existing contract instance is overwritten / lost.
Update this API to add support for adding, updating, and removing multiple contracts and contract interfaces, independently.
Add new types:
Contract
:
A contract that can be deployed to an account.
The initializer checks the code and aborts if:
pub struct Contract {
pub let name: String
pub let code: [UInt8]
init(name: String, code: [UInt8])
}
DeployedContract
:
A contract that is deployed at a given account.
pub struct DeployedContract {
pub let contract: Contract
pub let address: Address
}
AuthAccountContracts
:
The deployed contracts of an authorized account.
Allows introspection, and also addition and removal.
fun add(contract: Contract, ... initializerArguments): DeployedContract
fun update__experimental(contract: Contract): DeployedContract
fun get(name: String): DeployedContract?
fun delete(name: String): DeployedContract?
Add the following member to AuthAccount
:
let contracts: AuthAccountContracts
Add special function migrate
to composites, the migration function, which is called automatically as part of AuthAccount.contracts.update
:
migrate
is a special function, like init
and destroy
;fun migrate()
won't be allowed.migrate
behaves similar to init
[UInt8]
, could be replaced with a dedicated Code
type,Code
could be added. This would allow use of the contract after it is added/updated (the static analysis needs to have access to the type declarations in the passed code).migrate
?
The controller parameter is not used.
Remove the parameter from the interface.
runtime.Interface
's storage functions (get/set) only have an owner parameterCadence programs should indicate in what version of Cadence they are written in.
#version(_ version: String)
, e.g. #version("0.5")
at the beginning of programsversion string
field to ast.Program
When trying to store a function in a smart contract, the runtime panics and crashes.
pub contract Controller {
pub var operator: AnyStruct?
init(){
self.operator = fun(): Int{
return 1
}
}
}
The checker should reject this
The focus of this issue is just to not allow functions to be stored in fields.
In the future we will also have to reject more types, this is a starting place.
CompositeValue.SetMember
: check if valid value (StringValue
, BoolValue
, ...), recurse into nested value (e.g. arrays)AnyStruct
Checker.declareCompositeMembersAndValue
:
compositeType.Members = members
:check member.TypeAnnotation.Type
is valid type (StringType
, BoolType
, ...),Type parameters can have an optional type bound, e.g T<U: &Any>
.
Check that the type argument is a subtype of the type bound.
At the moment there is no pretty print solution for Cadence, which leads to simple mistakes - single quotes for String literals, for example - and waste of time, when you would reformat your code to make it more readable.
Prettier is a de-facto goto solution for pretty print in web development. And it have support for plugins. Main repository also have multiple implementations - Swift, for example - which can serve as inspiration and guidance to build one for Cadence.
Implement a function to return the least common supertype.
This improves type checking for:
See "Types and Programming Languages, 16.3 Joins and Meets"
In the following example y
should be inferred to String?
:
let x: String? = ""
let y = true ? nil : x
Consider the code:
pub contract interface FungibleTokenInterface {
pub var paused: Bool
...
...
pub resource interface Vault: Provider, Receiver, Balance { //same as in the spec
pub var balance: UFix64
pub fun withdraw(amount: UFix64): @Vault {
pre {
FungibleTokenInterface.paused == false: "Can't withdraw when function is paused"
...
}
}
}
Here I defined a contract variable in the interface called paused
. But I can't call that in the pre-condition of the withdraw method on the Vault interface.
Deploying this contract gives the error- "can't access FungibleTokenInterface.
"
I had to shift the pre condition code to my actual contract. I just think putting this in the interface makes things cleaner.
Emulator is crashing
acct.link<&FungibleToken.Vault{FungibleToken.Receiver, FungibleToken.Balance}>(/public/MainReceiver, target: /storage/MainVault)
pub fun main(): &FungibleToken.Vault{FungibleToken.Balance} {
let acct1 = getAccount(0x01cf0e2f2f715450)
let acct1ReceiverRef = acct1.getCapability(/public/MainReceiver)!
.borrow<&FungibleToken.Vault{FungibleToken.Balance}>()!
return acct1ReceiverRef
panic: cannot convert value of type *interpreter.StorageReferenceValue
Such scripts shouldn't crash the emulator at run-time, but rather have to report an error.
Currently the runtime uses the wrapPanic
function to capture panics that originate from method calls on the runtime.Interface
object. The current implementation requires the caller to remember to wrap each call with wrapPanic
, which is prone to bugs.
Introduce an adapter for runtime.Interface
that acts as a simple proxy to catch panics originating from the host environment.
The following program crashes the checker:
let x = y.isInstance(Type<Int>())
with
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x14d97ea]
goroutine 15 [running]:
testing.tRunner.func1.1(0x1742f40, 0x1fee2e0)
/usr/local/Cellar/go/1.14.2_1/libexec/src/testing/testing.go:940 +0x2f5
testing.tRunner.func1(0xc0000cc7e0)
/usr/local/Cellar/go/1.14.2_1/libexec/src/testing/testing.go:943 +0x3f9
panic(0x1742f40, 0x1fee2e0)
/usr/local/Cellar/go/1.14.2_1/libexec/src/runtime/panic.go:969 +0x166
github.com/onflow/cadence/runtime/sema.(*Checker).recordResourceInvalidation(0xc000aa8100, 0x1997ea0, 0xc00028f710, 0x0, 0x0, 0x2, 0x0)
/Users/bastian/Documents/work/cadence/runtime/sema/checker.go:1411 +0x3a
github.com/onflow/cadence/runtime/sema.(*Checker).checkInvocationExpression(0xc000aa8100, 0xc000278960, 0x0, 0x0)
/Users/bastian/Documents/work/cadence/runtime/sema/check_invocation_expression.go:158 +0x5e0
github.com/onflow/cadence/runtime/sema.(*Checker).VisitInvocationExpression(0xc000aa8100, 0xc000278960, 0xc000aa8100, 0x2795e10)
/Users/bastian/Documents/work/cadence/runtime/sema/check_invocation_expression.go:27 +0x3f
github.com/onflow/cadence/runtime/ast.(*InvocationExpression).AcceptExp(...)
/Users/bastian/Documents/work/cadence/runtime/ast/expression.go:339
github.com/onflow/cadence/runtime/ast.(*InvocationExpression).Accept(0xc000278960, 0x19b8640, 0xc000aa8100, 0xb, 0x2)
/Users/bastian/Documents/work/cadence/runtime/ast/expression.go:335 +0x62
github.com/onflow/cadence/runtime/sema.(*Checker).visitVariableDeclaration(0xc000aa8100, 0xc0000d58c0, 0x0)
/Users/bastian/Documents/work/cadence/runtime/sema/check_variable_declaration.go:43 +0xc2
github.com/onflow/cadence/runtime/sema.(*Checker).VisitVariableDeclaration(0xc000aa8100, 0xc0000d58c0, 0x10, 0xc0000bc3e8)
/Users/bastian/Documents/work/cadence/runtime/sema/check_variable_declaration.go:27 +0x3a
github.com/onflow/cadence/runtime/ast.(*VariableDeclaration).Accept(0xc0000d58c0, 0x19b8640, 0xc000aa8100, 0x1, 0x0)
/Users/bastian/Documents/work/cadence/runtime/ast/variable_declaration.go:51 +0x3e
github.com/onflow/cadence/runtime/sema.(*Checker).VisitProgram(0xc000aa8100, 0xc0000bc370, 0x0, 0x0)
/Users/bastian/Documents/work/cadence/runtime/sema/checker.go:453 +0x417
github.com/onflow/cadence/runtime/ast.(*Program).Accept(...)
/Users/bastian/Documents/work/cadence/runtime/ast/program.go:53
github.com/onflow/cadence/runtime/sema.(*Checker).Check.func1(...)
/Users/bastian/Documents/work/cadence/runtime/sema/checker.go:326
github.com/onflow/cadence/runtime/sema.(*Checker).Check(0xc000aa8100, 0x1977580, 0x1960f70)
/Users/bastian/Documents/work/cadence/runtime/sema/checker.go:331 +0x154
github.com/onflow/cadence/runtime/tests/checker.ParseAndCheckWithOptions(0xc0000cc7e0, 0x1852f87, 0x35, 0x0, 0x1977580, 0x1960f70, 0x0, 0x0, 0x0, 0x0, ...)
/Users/bastian/Documents/work/cadence/runtime/tests/checker/utils.go:95 +0x232
github.com/onflow/cadence/runtime/tests/checker.ParseAndCheck(...)
/Users/bastian/Documents/work/cadence/runtime/tests/checker/utils.go:36
github.com/onflow/cadence/runtime/tests/checker.TestCheckResourceMoveMemberInvocation.func6(0xc0000cc7e0)
/Users/bastian/Documents/work/cadence/runtime/tests/checker/resources_test.go:4510 +0x89
testing.tRunner(0xc0000cc7e0, 0x18998c8)
/usr/local/Cellar/go/1.14.2_1/libexec/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
/usr/local/Cellar/go/1.14.2_1/libexec/src/testing/testing.go:1042 +0x357
Discovered using the fuzzer.
The problem occurs when invoking a member of an undeclared variable
In a function, a variable can be declared in a subscope with the same name as another variable in the function, which shadows the previously declared variable. This shouldn't be allowed.
pub contract Nodes {
init() {
var node = 1
var i = 1
// are we supposed to be allowed to use a name that we've already used?
while i < 10 {
// which num is used for the assignment?
var node = 3
log(node)
i = i + 1
}
log(node)
}
}
Checker should report an error that the variable with the same name cannot be declared in a subscope.
So assets/tokens etc. are stored locally on an account's storage as a resource and not on a smart contract. Also, 2 resources can't have the same path.
So are we expecting users of Flow to not just remember their account address and private key but also where they store what resource?
Creating some kind of resource standard (and hoping that users comply) wouldn't work because what if they already had some resource stored there, or if a malicious user poses as my erc20 token and convinces the user to store it at that particular resource?
Storing a database table of the resource path for each account that uses my contract is also hard because as a developer, how will I know who is using my smart contract, until the event on the SC is fired.
1 idea that may work is to block certain resource paths on ALL accounts.
So for the flow token, what if you block "`/storage/FlowToken" everywhere. And do this is for every SC created which deals with assets.
And there is a community-based GitHub repo that shows which resource paths are blocked for which asset.
Doing this allows automation too. Now I can automatically create a link from storage to the public domain for each account allowing anyone to seamlessly send tokens to someone else.
If a function has a non-Void return type, the return statements in the function must have a return value.
However, currently no error is reported when the a return statement has no value.
The following program is invalid, because the return statement has no return value, but no error is reported:
fun test(): Int {
return
}
We might update the serialization format in the future.
Future-proof the current serialization format by adding a magic string with a version.
In our tests, we use ExpectCheckerErrors
to check expected errors from the checker.
However when there are more or less expected errors then then actual errors, it would print error message like this:
--- FAIL: TestRuntimeTransactionTopLevelDeclarations/transaction_with_resource (0.00s)
utils.go:110:
Error Trace: utils.go:110
runtime_test.go:3236
Error: "[resource declarations are not valid at the top-level]" should have 2 item(s), but has 1
Test: TestRuntimeTransactionTopLevelDeclarations/transaction_with_resource
It doesn't tell what error was missing.
And when we expect no checker error, but actually had some, the currently error message only prints "Checking failed". And we have to use cmd.PrettyPrintError
to print the detailed message.
It would be great if
The following event IDs are now emitted with a "S"
prefix, which introduces a breaking change for downstream Flow SDKs.
S.flow.AccountCreated
S.flow.AccountKeyAdded
S.flow.AccountKeyRemoved
S.flow.AccountCodeUpdated
https://github.com/onflow/cadence/blob/master/runtime/stdlib/flow_builtin.go#L224-L246
Currently the VM uses the type ID produced by Cadence to index events, and users can query for events using these IDs. It may be the case that the VM should sanitize these IDs, rather than using the exact ID that Cadence produces.
We've been talking about how we like cadence projects to be organized in github repos and have come up with a proposal that could use some feedback. The ways that out projects are currently organized is not very good and makes it seem like more of a Go project than cadence project, so we decided to change the hierarchy to put the cadence files more in the front.
Here is our proposal:
contracts/
contains the cadence smart contract source code
transactions/
contains the scripts and transactions that are used to interact with the smartcontracts
lib/go
, lib/js
, etc contains language specific tools and packages for interacting with the smart contracts. These can include packages to return formatted transactions, contracts, and tests.
Within the lib/go/
directory, we have broken up it into 3 packages:
contracts
: package for getting the text of the contracts in a repo, replacing some names and fields for customization
templates
: packages for returning common transaction templates for the smart contracts. Uses the transaction templates in transactions/
to construct them.
test
: contains all the automated test related code for testing your smart contract
This is still a work in progress, so please give feedback about the structure of the repo, the package organization, and whatever else you feel is important.
The newly added toBytes
and toBigEndianBytes
methods return byte arrays typed as [UInt8]
, whereas the Crypto
contract accepts public keys, signatures and messages typed as [Int]
. To support compatibility between these APIs, the types should be consistent.
[UInt8]
is more correct -- is there any reason not to update all existing byte array representations to be typed this way?
It was suggested that in addition/instead of borrow<T>()
function calls,
the dedicated syntax borrow!/borrow? ... [as ...]
might be more readable and explicit.
To be able to process the AST outside of Go, for example to visualize it in an AST explorer, or use it for pretty-printing, the JSON representation must be improved:
Implement and test json.MarshalJSON
for the following types, adding a Type
property where the element is polymorphic (e.g. expressions), and position information as StartPos
and EndPos
properties:
Access
Argument
Block
FunctionBlock
Condition
CompositeDeclaration
FieldDeclaration
ConditionKind
BoolExpression
NilExpression
StringExpression
IntegerExpression
FixedPointExpression
ArrayExpression
DictionaryExpression
IdentifierExpression
InvocationExpression
MemberExpression
IndexExpression
ConditionalExpression
UnaryExpression
BinaryExpression
FunctionExpression
CastingExpression
CreateExpression
DestroyExpression
ReferenceExpression
ForceExpression
PathExpression
FunctionDeclaration
SpecialFunctionDeclaration
ImportDeclaration
Identifier
IdentifierLocation
StringLocation
AddressLocation
InterfaceDeclaration
Members
Operation
Parameter
ParameterList
Program
ReturnStatement
BreakStatement
ContinueStatement
IfStatement
WhileStatement
ForStatement
EmitStatement
AssignmentStatement
SwapStatement
ExpressionStatement
TransactionDeclaration
Transfer
TransferOperation
TypeAnnotation
NominalType
OptionalType
VariableSizedType
ConstantSizedType
DictionaryType
FunctionType
ReferenceType
RestrictedType
InstantiationType
VariableDeclaration
VariableKind
DeclarationKind
CompositeKind
PragmaDeclaration
We've added the Type
type and value. Make sure it can be saved to and loaded from storage.
TypeValue
is storableThe assert
statement is behaving in a strange way in v0.5.0-beta1
.
This script will panic due to the failed assertion:
pub fun main(): Int {
assert(1 == 2)
return 42
}
However, this script will return successfully with a value of 42:
pub fun main(): Int {
assert 1 == 2
return 42
}
Could this be a parser bug?
The Capability
type was introduced in the new storage interface.
If it could be made generic and have a type parameter, then the repeated explicit type argument for borrow
call-sites could be removed.
T<U_1, ..., U_n>
)Capability
generic, add type parameterA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.