From 7b7a70a5a7f379056380987da88724cac89eea02 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 29 Mar 2024 15:02:27 -0500 Subject: [PATCH 01/39] update IFlowEVMNFTBridge event value --- cadence/contracts/bridge/IFlowEVMNFTBridge.cdc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cadence/contracts/bridge/IFlowEVMNFTBridge.cdc b/cadence/contracts/bridge/IFlowEVMNFTBridge.cdc index 2225997d..11516b37 100644 --- a/cadence/contracts/bridge/IFlowEVMNFTBridge.cdc +++ b/cadence/contracts/bridge/IFlowEVMNFTBridge.cdc @@ -5,6 +5,7 @@ import "EVM" import "FlowEVMBridgeConfig" import "FlowEVMBridgeUtils" +import "CrossVMNFT" access(all) contract interface IFlowEVMNFTBridge { @@ -67,7 +68,7 @@ access(all) contract interface IFlowEVMNFTBridge { emit BridgedNFTToEVM( type: token.getType(), id: token.id, - evmID: 0, + evmID: CrossVMNFT.getEVMID(from: &token as &{NonFungibleToken.NFT}) ?? UInt256(token.id), to: FlowEVMBridgeUtils.getEVMAddressAsHexString(address: to), evmContractAddress: FlowEVMBridgeUtils.getEVMAddressAsHexString( address: self.getAssociatedEVMAddress(with: token.getType()) From 9b16a6838309077d82c7ec958f9384aed591ef14 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:46:45 -0600 Subject: [PATCH 02/39] add Serialize util contract to support URL encoding serialized metadata --- cadence/contracts/utils/Serialize.cdc | 150 ++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 cadence/contracts/utils/Serialize.cdc diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc new file mode 100644 index 00000000..441f61da --- /dev/null +++ b/cadence/contracts/utils/Serialize.cdc @@ -0,0 +1,150 @@ +/// This contract is a utility for serializing primitive types, arrays, and common metadata mapping formats to JSON +/// compatible strings. Also included are interfaces enabling custom serialization for structs and resources. +/// +/// Special thanks to @austinkline for the idea and initial implementation. +/// +access(all) +contract Serialize { + + /// Defines the interface for a struct that returns a serialized representation of itself + /// + access(all) + struct interface SerializableStruct { + access(all) fun serialize(): String + } + + /// Defines the interface for a resource that returns a serialized representation of itself + /// + access(all) + resource interface SerializableResource { + access(all) fun serialize(): String + } + + /// Method that returns a serialized representation of the given value or nil if the value is not serializable + /// + access(all) + fun tryToString(_ value: AnyStruct): String? { + // Call serialize on the value if available + if value.getType().isSubtype(of: Type<{SerializableStruct}>()) { + return (value as! {SerializableStruct}).serialize() + } + // Recursively serialize array & return + if value.getType().isSubtype(of: Type<[AnyStruct]>()) { + return self.arrayToString(value as! [AnyStruct]) + } + // Recursively serialize map & return + if value.getType().isSubtype(of: Type<{String: AnyStruct}>()) { + return self.mapToString(value as! {String: AnyStruct}) + } + // Handle primitive types & their respective optionals + switch value.getType() { + case Type(): + return value as! String + case Type(): + return value as? String ?? "nil" + case Type(): + return (value as! Character).toString() + case Type(): + return (value as? Character)?.toString() ?? "nil" + case Type(): + return self.boolToString(value as! Bool) + case Type(): + if value as? Bool == nil { + return "nil" + } + return self.boolToString(value as! Bool) + case Type
(): + return (value as! Address).toString() + case Type(): + return (value as? Address)?.toString() ?? "nil" + case Type(): + return (value as! Int8).toString() + case Type(): + return (value as! Int16).toString() + case Type(): + return (value as! Int32).toString() + case Type(): + return (value as! Int64).toString() + case Type(): + return (value as! Int128).toString() + case Type(): + return (value as! Int256).toString() + case Type(): + return (value as! Int).toString() + case Type(): + return (value as! UInt8).toString() + case Type(): + return (value as! UInt16).toString() + case Type(): + return (value as! UInt32).toString() + case Type(): + return (value as! UInt64).toString() + case Type(): + return (value as! UInt128).toString() + case Type(): + return (value as! UInt256).toString() + case Type(): + return (value as! Word8).toString() + case Type(): + return (value as! Word16).toString() + case Type(): + return (value as! Word32).toString() + case Type(): + return (value as! Word64).toString() + case Type(): + return (value as! Word128).toString() + case Type(): + return (value as! Word256).toString() + case Type(): + return (value as! UFix64).toString() + default: + return nil + } + } + + /// Method that returns a serialized representation of a provided boolean + /// + access(all) + fun boolToString(_ value: Bool): String { + return value ? "true" : "false" + } + + /// Method that returns a serialized representation of the given array or nil if the value is not serializable + /// + access(all) + fun arrayToString(_ arr: [AnyStruct]): String? { + var serializedArr = "[" + for i, element in arr { + let serializedElement = self.tryToString(element) + if serializedElement == nil { + return nil + } + serializedArr = serializedArr.concat("\"").concat(serializedElement!).concat("\"") + if i < arr.length - 1 { + serializedArr = serializedArr.concat(", ") + } + } + serializedArr.concat("]") + return serializedArr + } + + /// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not + /// serializable + /// + access(all) + fun mapToString(_ map: {String: AnyStruct}): String? { + var serializedMap = "{" + for i, key in map.keys { + let serializedValue = self.tryToString(map[key]!) + if serializedValue == nil { + return nil + } + serializedMap = serializedMap.concat("\"").concat(key).concat("\": \"").concat(serializedValue!).concat("\"}") + if i < map.length - 1 { + serializedMap = serializedMap.concat(", ") + } + } + serializedMap.concat("}") + return serializedMap + } +} From b14b5bafa5544b6dc900b352ec7148fa6bebe2f2 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Mar 2024 20:44:38 -0600 Subject: [PATCH 03/39] update Serialize util contract --- cadence/contracts/utils/Serialize.cdc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc index 441f61da..9ec9beaa 100644 --- a/cadence/contracts/utils/Serialize.cdc +++ b/cadence/contracts/utils/Serialize.cdc @@ -34,7 +34,7 @@ contract Serialize { } // Recursively serialize map & return if value.getType().isSubtype(of: Type<{String: AnyStruct}>()) { - return self.mapToString(value as! {String: AnyStruct}) + return self.dictToString(dict: value as! {String: AnyStruct}, excludedNames: nil) } // Handle primitive types & their respective optionals switch value.getType() { @@ -132,19 +132,24 @@ contract Serialize { /// serializable /// access(all) - fun mapToString(_ map: {String: AnyStruct}): String? { - var serializedMap = "{" - for i, key in map.keys { - let serializedValue = self.tryToString(map[key]!) + fun dictToString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { + if excludedNames != nil { + for k in excludedNames! { + dict.remove(key: k) + } + } + var serializedDict = "{" + for i, key in dict.keys { + let serializedValue = self.tryToString(dict[key]!) if serializedValue == nil { return nil } - serializedMap = serializedMap.concat("\"").concat(key).concat("\": \"").concat(serializedValue!).concat("\"}") - if i < map.length - 1 { - serializedMap = serializedMap.concat(", ") + serializedDict = serializedDict.concat("\"").concat(key).concat("\": \"").concat(serializedValue!).concat("\"}") + if i < dict.length - 1 { + serializedDict = serializedDict.concat(", ") } } - serializedMap.concat("}") - return serializedMap + serializedDict.concat("}") + return serializedDict } } From 6abeb315fb998aa5342d8c78b61c4f17d39ada9f Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:12:08 -0500 Subject: [PATCH 04/39] add Serialize test cases --- cadence/contracts/utils/Serialize.cdc | 12 +- cadence/tests/Serialize_tests.cdc | 212 ++++++++++++++++++++++++++ flow.json | 7 + 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 cadence/tests/Serialize_tests.cdc diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc index 9ec9beaa..a6f3ccf7 100644 --- a/cadence/contracts/utils/Serialize.cdc +++ b/cadence/contracts/utils/Serialize.cdc @@ -38,6 +38,8 @@ contract Serialize { } // Handle primitive types & their respective optionals switch value.getType() { + case Type(): + return "nil" case Type(): return value as! String case Type(): @@ -83,6 +85,8 @@ contract Serialize { return (value as! UInt128).toString() case Type(): return (value as! UInt256).toString() + case Type(): + return (value as! UInt).toString() case Type(): return (value as! Word8).toString() case Type(): @@ -102,6 +106,11 @@ contract Serialize { } } + access(all) + fun tryToJSONString(_ value: AnyStruct): String? { + return "\"".concat(self.tryToString(value) ?? "nil").concat("\"") + } + /// Method that returns a serialized representation of a provided boolean /// access(all) @@ -129,7 +138,8 @@ contract Serialize { } /// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not - /// serializable + /// serializable. The interface here is largely the same as as the `MetadataViews.dictToTraits` method, though here + /// a JSON-compatible String is returned instead of a `Traits` array. /// access(all) fun dictToString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { diff --git a/cadence/tests/Serialize_tests.cdc b/cadence/tests/Serialize_tests.cdc new file mode 100644 index 00000000..c01aa00f --- /dev/null +++ b/cadence/tests/Serialize_tests.cdc @@ -0,0 +1,212 @@ +import Test +import BlockchainHelpers + +import "Serialize" + +access(all) +let serializeAccount = Test.getAccount(0x0000000000000007) + +access(all) +fun setup() { + var err = Test.deployContract( + name: "Serialize", + path: "../contracts/utils/Serialize.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) +} + +access(all) +fun testIntsTryToJSONStringSucceeds() { + let i: Int = 127 + let i8: Int8 = 127 + let i16: Int16 = 127 + let i32: Int32 = 127 + let i64: Int64 = 127 + let i128: Int128 = 127 + let i256: Int256 = 127 + + let expected = "\"127\"" + + var actual = Serialize.tryToJSONString(i) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i8) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i16) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i32) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i64) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i128) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(i256) + Test.assertEqual(expected, actual!) +} + +access(all) +fun testUIntsTryToJSONStringSucceeds() { + let ui: UInt = 255 + let ui8: UInt8 = 255 + let ui16: UInt16 = 255 + let ui32: UInt32 = 255 + let ui64: UInt64 = 255 + let ui128: UInt128 = 255 + let ui256: UInt256 = 255 + + let expected = "\"255\"" + + var actual = Serialize.tryToJSONString(ui) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui8) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui16) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui32) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui64) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui128) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(ui256) + Test.assertEqual(expected, actual!) +} + +access(all) +fun testWordsTryToJSONStringSucceeds() { + let word8: Word8 = 255 + let word16: Word16 = 255 + let word32: Word32 = 255 + let word64: Word64 = 255 + let word128: Word128 = 255 + let word256: Word256 = 255 + + let expected = "\"255\"" + + var actual = Serialize.tryToJSONString(word8) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(word16) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(word32) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(word64) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(word128) + Test.assertEqual(expected, actual!) + + actual = Serialize.tryToJSONString(word256) + Test.assertEqual(expected, actual!) +} + +access(all) +fun testAddressTryToJSONStringSucceeds() { + let address: Address = 0x0000000000000007 + let addressOpt: Address? = nil + + let expected = "\"0x0000000000000007\"" + let expectedOpt = "\"nil\"" + + var actual = Serialize.tryToJSONString(address) + Test.assertEqual(expected, actual!) + + var actualOpt = Serialize.tryToJSONString(addressOpt) + Test.assertEqual(expectedOpt, actualOpt!) +} + +access(all) +fun testStringTryToJSONStringSucceeds() { + let str: String = "Hello, World!" + let strOpt: String? = nil + + let expected = "\"Hello, World!\"" + let expectedOpt = "\"nil\"" + + var actual = Serialize.tryToJSONString(str) + Test.assertEqual(expected, actual!) + + var actualOpt = Serialize.tryToJSONString(strOpt) + Test.assertEqual(expectedOpt, actualOpt!) +} + +access(all) +fun testCharacterTryToJSONStringSucceeds() { + let char: Character = "c" + let charOpt: Character? = nil + + let expected = "\"c\"" + let expectedOpt = "\"nil\"" + + var actual = Serialize.tryToJSONString(char) + Test.assertEqual(expected, actual!) + + var actualOpt = Serialize.tryToJSONString(charOpt) + Test.assertEqual(expectedOpt, actualOpt!) +} + +access(all) +fun testUFix64TryToJSONStringSucceeds() { + let uf64: UFix64 = UFix64.max + + let expected = "\"184467440737.09551615\"" + + var actual = Serialize.tryToJSONString(uf64) + Test.assertEqual(expected, actual!) +} + +access(all) +fun testBoolTryToJSONStringSucceeds() { + let t: Bool = true + let f: Bool = false + + let expectedTrue = "\"true\"" + let expectedFalse = "\"false\"" + + var actualTrue = Serialize.tryToJSONString(t) + var actualFalse = Serialize.tryToJSONString(f) + + Test.assertEqual(expectedTrue, actualTrue!) + Test.assertEqual(expectedFalse, actualFalse!) +} + +access(all) +fun testBoolToStringSucceeds() { + let t: Bool = true + let f: Bool = false + + let expectedTrue = "true" + let expectedFalse = "false" + + var actualTrue = Serialize.boolToString(t) + var actualFalse = Serialize.boolToString(f) + + Test.assertEqual(expectedTrue, actualTrue) + Test.assertEqual(expectedFalse, actualFalse) +} + +// access(all) +// fun testArrayToStringSucceeds() { +// let arr: [AnyStruct] = + +// let expected = "\"true\"" + +// var actual = Serialize.tryToJSONString(t) + +// Test.assertEqual(expectedTrue, actualTrue!) +// Test.assertEqual(expectedFalse, actualFalse!) +// } \ No newline at end of file diff --git a/flow.json b/flow.json index 9562450d..ff11de22 100644 --- a/flow.json +++ b/flow.json @@ -143,6 +143,13 @@ "emulator": "f8d6e0586b0a20c7" } }, + "Serialize": { + "source": "./cadence/contracts/utils/Serialize.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, "StringUtils": { "source": "./cadence/contracts/utils/StringUtils.cdc", "aliases": { From 230d39e8cc2a9f55eca82b2db2bc9412d1c0e0f0 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:33:25 -0500 Subject: [PATCH 05/39] fix array serialization --- cadence/contracts/utils/Serialize.cdc | 3 +-- cadence/tests/Serialize_tests.cdc | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc index a6f3ccf7..52c6c1d1 100644 --- a/cadence/contracts/utils/Serialize.cdc +++ b/cadence/contracts/utils/Serialize.cdc @@ -133,8 +133,7 @@ contract Serialize { serializedArr = serializedArr.concat(", ") } } - serializedArr.concat("]") - return serializedArr + return serializedArr.concat("]") } /// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not diff --git a/cadence/tests/Serialize_tests.cdc b/cadence/tests/Serialize_tests.cdc index c01aa00f..3a7ad0f5 100644 --- a/cadence/tests/Serialize_tests.cdc +++ b/cadence/tests/Serialize_tests.cdc @@ -199,14 +199,22 @@ fun testBoolToStringSucceeds() { Test.assertEqual(expectedFalse, actualFalse) } -// access(all) -// fun testArrayToStringSucceeds() { -// let arr: [AnyStruct] = +access(all) +fun testArrayToJSONStringSucceeds() { + let arr: [AnyStruct] = [ + 127, + 255, + "Hello, World!", + "c", + Address(0x0000000000000007), + UFix64.max, + true + ] -// let expected = "\"true\"" - -// var actual = Serialize.tryToJSONString(t) + let expected = "[\"127\", \"255\", \"Hello, World!\", \"c\", \"0x0000000000000007\", \"184467440737.09551615\", \"true\"]" -// Test.assertEqual(expectedTrue, actualTrue!) -// Test.assertEqual(expectedFalse, actualFalse!) -// } \ No newline at end of file + var actual = Serialize.arrayToString(arr) + + Test.assertEqual(expected, actual!) +} + From 511e2e48ae6011ab4a8acf9370bd9acb3effadd7 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 15 Mar 2024 18:37:00 -0500 Subject: [PATCH 06/39] update ExampleNFT Traits for serialization testability --- cadence/contracts/example-assets/ExampleNFT.cdc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cadence/contracts/example-assets/ExampleNFT.cdc b/cadence/contracts/example-assets/ExampleNFT.cdc index 6ae33b52..61f57017 100644 --- a/cadence/contracts/example-assets/ExampleNFT.cdc +++ b/cadence/contracts/example-assets/ExampleNFT.cdc @@ -109,10 +109,6 @@ access(all) contract ExampleNFT: NonFungibleToken { let excludedTraits = ["mintedTime", "foo"] let traitsView = MetadataViews.dictToTraits(dict: self.metadata, excludedNames: excludedTraits) - // mintedTime is a unix timestamp, we should mark it with a displayType so platforms know how to show it. - let mintedTimeTrait = MetadataViews.Trait(name: "mintedTime", value: self.metadata["mintedTime"]!, displayType: "Date", rarity: nil) - traitsView.addTrait(mintedTimeTrait) - // foo is a trait with its own rarity let fooTraitRarity = MetadataViews.Rarity(score: 10.0, max: 100.0, description: "Common") let fooTrait = MetadataViews.Trait(name: "foo", value: self.metadata["foo"], displayType: nil, rarity: fooTraitRarity) From ff4e00011abcdc4438abff792440a60f99f5041c Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 15:45:05 -0500 Subject: [PATCH 07/39] update serialization utils & tests --- .gitignore | 5 + .../utils/SerializationInterfaces.cdc | 30 +++ cadence/contracts/utils/Serialize.cdc | 141 +++++++------ cadence/contracts/utils/SerializeNFT.cdc | 185 ++++++++++++++++++ cadence/scripts/serialize/serialize_nft.cdc | 20 ++ .../serialize_nft_from_open_sea_strategy.cdc | 21 ++ cadence/tests/Serialize_tests.cdc | 109 ++++++++--- cadence/tests/serialize_nft_tests.cdc | 130 ++++++++++++ flow.json | 25 ++- 9 files changed, 564 insertions(+), 102 deletions(-) create mode 100644 cadence/contracts/utils/SerializationInterfaces.cdc create mode 100644 cadence/contracts/utils/SerializeNFT.cdc create mode 100644 cadence/scripts/serialize/serialize_nft.cdc create mode 100644 cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc create mode 100644 cadence/tests/serialize_nft_tests.cdc diff --git a/.gitignore b/.gitignore index 6a3b4a5c..0a5466db 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,9 @@ docs/ # Dotenv file .env +# flow-evm-gateway db/ files db/ + +# Cadence test framework coverage +coverage.json +coverage.lcov diff --git a/cadence/contracts/utils/SerializationInterfaces.cdc b/cadence/contracts/utils/SerializationInterfaces.cdc new file mode 100644 index 00000000..667982a5 --- /dev/null +++ b/cadence/contracts/utils/SerializationInterfaces.cdc @@ -0,0 +1,30 @@ +/// The contract defines an interface for serialization strategies that can be used to serialize the struct or resource +/// according to a specific format. +/// +access(all) contract SerializationInterfaces { + + /// A SerializationStrategy takes a reference to a SerializableResource or SerializableStruct and returns a + /// serialized representation of it. The strategy is responsible for determining the structure of the serialized + /// representation and the format of the serialized data. + /// + access(all) + struct interface SerializationStrategy { + /// Returns the types supported by the implementing strategy + /// + access(all) view fun getSupportedTypes(): [Type] { + return [] + } + + /// Returns serialized representation of the given resource according to the format of the implementing strategy + /// + access(all) fun serializeResource(_ r: &AnyResource): String? { + return nil + } + + /// Returns serialized representation of the given struct according to the format of the implementing strategy + /// + access(all) fun serializeStruct(_ s: AnyStruct): String? { + return nil + } + } +} diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc index 52c6c1d1..9c73f430 100644 --- a/cadence/contracts/utils/Serialize.cdc +++ b/cadence/contracts/utils/Serialize.cdc @@ -1,3 +1,9 @@ +import "ViewResolver" +import "MetadataViews" +import "NonFungibleToken" + +import "SerializationInterfaces" + /// This contract is a utility for serializing primitive types, arrays, and common metadata mapping formats to JSON /// compatible strings. Also included are interfaces enabling custom serialization for structs and resources. /// @@ -6,129 +12,115 @@ access(all) contract Serialize { - /// Defines the interface for a struct that returns a serialized representation of itself + /// A basic serialization strategy that supports serializing resources and structs to JSON-compatible strings. /// access(all) - struct interface SerializableStruct { - access(all) fun serialize(): String - } - - /// Defines the interface for a resource that returns a serialized representation of itself - /// - access(all) - resource interface SerializableResource { - access(all) fun serialize(): String + struct JSONStringStrategy : SerializationInterfaces.SerializationStrategy { + /// Returns the types this stategy will attempt to serialize + /// + access(all) view fun getSupportedTypes(): [Type] { + return [Type<@AnyResource>(), Type()] + } + /// Returns the resource serialized on its identifier as an escaped JSON string + /// + access(all) fun serializeResource(_ r: &AnyResource): String? { + return Serialize.tryToJSONString(r.getType().identifier) + } + /// Returns the an escaped JSON string of the provided struct, calling through to Serialize.tryToJSONString + /// with the provided value + /// + access(all) fun serializeStruct(_ s: AnyStruct): String? { + return Serialize.tryToJSONString(s) + } } /// Method that returns a serialized representation of the given value or nil if the value is not serializable /// access(all) - fun tryToString(_ value: AnyStruct): String? { - // Call serialize on the value if available - if value.getType().isSubtype(of: Type<{SerializableStruct}>()) { - return (value as! {SerializableStruct}).serialize() - } + fun tryToJSONString(_ value: AnyStruct): String? { // Recursively serialize array & return if value.getType().isSubtype(of: Type<[AnyStruct]>()) { - return self.arrayToString(value as! [AnyStruct]) + return self.arrayToJSONString(value as! [AnyStruct]) } // Recursively serialize map & return if value.getType().isSubtype(of: Type<{String: AnyStruct}>()) { - return self.dictToString(dict: value as! {String: AnyStruct}, excludedNames: nil) + return self.dictToJSONString(dict: value as! {String: AnyStruct}, excludedNames: nil) } - // Handle primitive types & their respective optionals + // Handle primitive types & optionals switch value.getType() { case Type(): - return "nil" + return "\"nil\"" case Type(): - return value as! String + return "\"".concat(value as! String).concat("\"") case Type(): - return value as? String ?? "nil" + return "\"".concat(value as? String ?? "nil").concat("\"") case Type(): - return (value as! Character).toString() - case Type(): - return (value as? Character)?.toString() ?? "nil" + return "\"".concat((value as! Character).toString()).concat("\"") case Type(): - return self.boolToString(value as! Bool) - case Type(): - if value as? Bool == nil { - return "nil" - } - return self.boolToString(value as! Bool) + return "\"".concat(value as! Bool ? "true" : "false").concat("\"") case Type
(): - return (value as! Address).toString() + return "\"".concat((value as! Address).toString()).concat("\"") case Type(): - return (value as? Address)?.toString() ?? "nil" + return "\"".concat((value as? Address)?.toString() ?? "nil").concat("\"") case Type(): - return (value as! Int8).toString() + return "\"".concat((value as! Int8).toString()).concat("\"") case Type(): - return (value as! Int16).toString() + return "\"".concat((value as! Int16).toString()).concat("\"") case Type(): - return (value as! Int32).toString() + return "\"".concat((value as! Int32).toString()).concat("\"") case Type(): - return (value as! Int64).toString() + return "\"".concat((value as! Int64).toString()).concat("\"") case Type(): - return (value as! Int128).toString() + return "\"".concat((value as! Int128).toString()).concat("\"") case Type(): - return (value as! Int256).toString() + return "\"".concat((value as! Int256).toString()).concat("\"") case Type(): - return (value as! Int).toString() + return "\"".concat((value as! Int).toString()).concat("\"") case Type(): - return (value as! UInt8).toString() + return "\"".concat((value as! UInt8).toString()).concat("\"") case Type(): - return (value as! UInt16).toString() + return "\"".concat((value as! UInt16).toString()).concat("\"") case Type(): - return (value as! UInt32).toString() + return "\"".concat((value as! UInt32).toString()).concat("\"") case Type(): - return (value as! UInt64).toString() + return "\"".concat((value as! UInt64).toString()).concat("\"") case Type(): - return (value as! UInt128).toString() + return "\"".concat((value as! UInt128).toString()).concat("\"") case Type(): - return (value as! UInt256).toString() + return "\"".concat((value as! UInt256).toString()).concat("\"") case Type(): - return (value as! UInt).toString() + return "\"".concat((value as! UInt).toString()).concat("\"") case Type(): - return (value as! Word8).toString() + return "\"".concat((value as! Word8).toString()).concat("\"") case Type(): - return (value as! Word16).toString() + return "\"".concat((value as! Word16).toString()).concat("\"") case Type(): - return (value as! Word32).toString() + return "\"".concat((value as! Word32).toString()).concat("\"") case Type(): - return (value as! Word64).toString() + return "\"".concat((value as! Word64).toString()).concat("\"") case Type(): - return (value as! Word128).toString() + return "\"".concat((value as! Word128).toString()).concat("\"") case Type(): - return (value as! Word256).toString() + return "\"".concat((value as! Word256).toString()).concat("\"") case Type(): - return (value as! UFix64).toString() + return "\"".concat((value as! UFix64).toString()).concat("\"") default: return nil } - } - access(all) - fun tryToJSONString(_ value: AnyStruct): String? { - return "\"".concat(self.tryToString(value) ?? "nil").concat("\"") - } - - /// Method that returns a serialized representation of a provided boolean - /// - access(all) - fun boolToString(_ value: Bool): String { - return value ? "true" : "false" } - /// Method that returns a serialized representation of the given array or nil if the value is not serializable + /// Returns a serialized representation of the given array or nil if the value is not serializable /// access(all) - fun arrayToString(_ arr: [AnyStruct]): String? { + fun arrayToJSONString(_ arr: [AnyStruct]): String? { var serializedArr = "[" for i, element in arr { - let serializedElement = self.tryToString(element) + let serializedElement = self.tryToJSONString(element) if serializedElement == nil { return nil } - serializedArr = serializedArr.concat("\"").concat(serializedElement!).concat("\"") + serializedArr = serializedArr.concat(serializedElement!) if i < arr.length - 1 { serializedArr = serializedArr.concat(", ") } @@ -136,12 +128,12 @@ contract Serialize { return serializedArr.concat("]") } - /// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not - /// serializable. The interface here is largely the same as as the `MetadataViews.dictToTraits` method, though here + /// Returns a serialized representation of the given String-indexed mapping or nil if the value is not serializable. + /// The interface here is largely the same as as the `MetadataViews.dictToTraits` method, though here /// a JSON-compatible String is returned instead of a `Traits` array. /// access(all) - fun dictToString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { + fun dictToJSONString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { if excludedNames != nil { for k in excludedNames! { dict.remove(key: k) @@ -149,16 +141,15 @@ contract Serialize { } var serializedDict = "{" for i, key in dict.keys { - let serializedValue = self.tryToString(dict[key]!) + let serializedValue = self.tryToJSONString(dict[key]!) if serializedValue == nil { return nil } - serializedDict = serializedDict.concat("\"").concat(key).concat("\": \"").concat(serializedValue!).concat("\"}") + serializedDict = serializedDict.concat(self.tryToJSONString(key)!).concat(": ").concat(serializedValue!) if i < dict.length - 1 { serializedDict = serializedDict.concat(", ") } } - serializedDict.concat("}") - return serializedDict + return serializedDict.concat("}") } } diff --git a/cadence/contracts/utils/SerializeNFT.cdc b/cadence/contracts/utils/SerializeNFT.cdc new file mode 100644 index 00000000..4b36a643 --- /dev/null +++ b/cadence/contracts/utils/SerializeNFT.cdc @@ -0,0 +1,185 @@ +import "ViewResolver" +import "MetadataViews" +import "NonFungibleToken" + +import "SerializationInterfaces" +import "Serialize" + +/// This contract defines methods for serializing NFT metadata as a JSON compatible string, according to the common +/// OpenSea metadata format. NFTs can be serialized by reference via contract methods or via the +/// OpenSeaMetadataSerializationStrategy struct. +/// +access(all) contract SerializeNFT { + + /// This struct will serialize NFT metadata as a JSON-compatible URI according to the OpenSea metadata standard + /// + access(all) + struct OpenSeaMetadataSerializationStrategy : SerializationInterfaces.SerializationStrategy { + /// Returns the types this strategy is intended to serialize + /// + access(all) view fun getSupportedTypes(): [Type] { + return [ + Type<@{NonFungibleToken.NFT}>(), + Type(), + Type(), + Type() + ] + } + + /// Serializes the given NFT (as &AnyResource) as a JSON compatible string in the format of an + /// OpenSea-compatible metadata URI. If the given resource is not an NFT, this method returns nil. + /// + /// Reference: https://docs.opensea.io/docs/metadata-standards + /// + access(all) fun serializeResource(_ r: &AnyResource): String? { + if r.getType().isSubtype(of: Type<@{NonFungibleToken.NFT}>()) { + let nft = r as! &{NonFungibleToken.NFT} + return SerializeNFT.serializeNFTMetadataAsURI(nft) + } + return nil + } + + /// Serializes the given struct as a JSON compatible string in the format that conforms with overlapping values + /// expected by the OpenSea metadata standard. If the given struct is not a Display, NFTCollectionDisplay, or + /// Traits view, this method returns nil. + /// + access(all) fun serializeStruct(_ s: AnyStruct): String? { + switch s.getType() { + case Type(): + let view = s as! MetadataViews.NFTCollectionDisplay + return SerializeNFT.serializeNFTDisplay(nftDisplay: nil, collectionDisplay: view) + case Type(): + let view = s as! MetadataViews.Display + return SerializeNFT.serializeNFTDisplay(nftDisplay: view, collectionDisplay: nil) + case Type(): + let view = s as! MetadataViews.Traits + return SerializeNFT.serializeNFTTraitsAsAttributes(view) + default: + return nil + + } + } + } + + /// Serializes the metadata (as a JSON compatible String) for a given NFT according to formats expected by EVM + /// platforms like OpenSea. If you are a project owner seeking to expose custom traits on bridged NFTs and your + /// Trait.value is not natively serializable, you can implement a custom serialization method with the + /// `{SerializableStruct}` interface's `serialize` method. + /// + /// Reference: https://docs.opensea.io/docs/metadata-standards + /// + /// + /// @returns: A JSON compatible string containing the serialized display & collection display views as: + /// `{ + /// \"name\": \"\", + /// \"description\": \"\", + /// \"image\": \"\", + /// \"external_url\": \"\", + /// \"attributes\": [{\"trait_type\": \"\", \"value\": \"\"}, {...}] + /// }` + access(all) + fun serializeNFTMetadataAsURI(_ nft: &{NonFungibleToken.NFT}): String { + // Serialize the display values from the NFT's Display & NFTCollectionDisplay views + let nftDisplay = nft.resolveView(Type()) as! MetadataViews.Display? + let collectionDisplay = nft.resolveView(Type()) as! MetadataViews.NFTCollectionDisplay? + let display = self.serializeNFTDisplay(nftDisplay: nftDisplay, collectionDisplay: collectionDisplay) + + // Get the Traits view from the NFT, returning early if no traits are found + let traits = nft.resolveView(Type()) as! MetadataViews.Traits? + let attributes = self.serializeNFTTraitsAsAttributes(traits ?? MetadataViews.Traits([])) + + // Return an empty string if nothing is serializable + if display == nil && attributes == nil { + return "" + } + // Init the data format prefix & concatenate the serialized display & attributes + var serializedMetadata= "data:application/json;ascii,{" + if display != nil { + serializedMetadata = serializedMetadata.concat(display!) + } + if display != nil && attributes != nil { + serializedMetadata = serializedMetadata.concat(", ") + } + if attributes != nil { + serializedMetadata = serializedMetadata.concat(attributes!) + } + return serializedMetadata.concat("}") + } + + /// Serializes the display & collection display views of a given NFT as a JSON compatible string + /// + /// @param nftDisplay: The NFT's Display view from which values `name`, `description`, and `thumbnail` are serialized + /// @param collectionDisplay: The NFT's NFTCollectionDisplay view from which the `externalURL` is serialized + /// + /// @returns: A JSON compatible string containing the serialized display & collection display views as: + /// \"name\": \"\", \"description\": \"\", \"image\": \"\", \"external_url\": \"\", + /// + access(all) + fun serializeNFTDisplay(nftDisplay: MetadataViews.Display?, collectionDisplay: MetadataViews.NFTCollectionDisplay?): String? { + // Return early if both values are nil + if nftDisplay == nil && collectionDisplay == nil { + return nil + } + + // Initialize JSON fields + let name = "\"name\": " + let description = "\"description\": " + let image = "\"image\": " + let externalURL = "\"external_url\": " + var serializedResult = "" + + // Append results from the Display view to the serialized JSON compatible string + if nftDisplay != nil { + serializedResult = serializedResult + .concat(name).concat(Serialize.tryToJSONString(nftDisplay!.name)!).concat(", ") + .concat(description).concat(Serialize.tryToJSONString(nftDisplay!.description)!).concat(", ") + .concat(image).concat(Serialize.tryToJSONString(nftDisplay!.thumbnail.uri())!) + // Return here if collectionDisplay is not present + if collectionDisplay == nil { + return serializedResult + } + } + + // Append a comma if both Display & NFTCollection Display views are present + if nftDisplay != nil { + serializedResult = serializedResult.concat(", ") + } else { + // Otherwise, append the name & description fields from the NFTCollectionDisplay view, foregoing image + serializedResult = serializedResult + .concat(name).concat(Serialize.tryToJSONString(collectionDisplay!.name)!).concat(", ") + .concat(description).concat(Serialize.tryToJSONString(collectionDisplay!.description)!).concat(", ") + } + + return serializedResult + .concat(externalURL) + .concat(Serialize.tryToJSONString(collectionDisplay!.externalURL.url)!) + } + + /// Serializes given Traits view as a JSON compatible string. If a given Trait is not serializable, it is skipped + /// and not included in the serialized result. + /// + /// @param traits: The Traits view to be serialized + /// + /// @returns: A JSON compatible string containing the serialized traits as: + /// `\"attributes\": [{\"trait_type\": \"\", \"value\": \"\"}, {...}]` + /// + access(all) + fun serializeNFTTraitsAsAttributes(_ traits: MetadataViews.Traits): String { + // Serialize each trait as an attribute, building the serialized JSON compatible string + var serializedResult = "\"attributes\": [" + for i, trait in traits!.traits { + let value = Serialize.tryToJSONString(trait.value) + if value == nil { + continue + } + serializedResult = serializedResult.concat("{") + .concat("\"trait_type\": ").concat(Serialize.tryToJSONString(trait.name)!) + .concat(", \"value\": ").concat(value!) + .concat("}") + if i < traits!.traits.length - 1 { + serializedResult = serializedResult.concat(",") + } + } + return serializedResult.concat("]") + } +} diff --git a/cadence/scripts/serialize/serialize_nft.cdc b/cadence/scripts/serialize/serialize_nft.cdc new file mode 100644 index 00000000..3cb72baa --- /dev/null +++ b/cadence/scripts/serialize/serialize_nft.cdc @@ -0,0 +1,20 @@ +import "ViewResolver" +import "MetadataViews" +import "NonFungibleToken" + +import "SerializeNFT" + +access(all) +fun main(address: Address, storagePathIdentifier: String, id: UInt64): String? { + let storagePath = StoragePath(identifier: storagePathIdentifier) + ?? panic("Could not construct StoragePath from identifier") + if let collection = getAuthAccount(address).storage + .borrow<&{NonFungibleToken.Collection}>( + from: storagePath + ) { + if let nft = collection.borrowNFT(id) { + return SerializeNFT.serializeNFTMetadataAsURI(nft) + } + } + return nil +} diff --git a/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc b/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc new file mode 100644 index 00000000..95b8d1e2 --- /dev/null +++ b/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc @@ -0,0 +1,21 @@ +import "ViewResolver" +import "MetadataViews" +import "NonFungibleToken" + +import "SerializeNFT" + +access(all) +fun main(address: Address, storagePathIdentifier: String, id: UInt64): String? { + let storagePath = StoragePath(identifier: storagePathIdentifier) + ?? panic("Could not construct StoragePath from identifier") + if let collection = getAuthAccount(address).storage + .borrow<&{NonFungibleToken.Collection}>( + from: storagePath + ) { + if let nft = collection.borrowNFT(id) { + let strategy = SerializeNFT.OpenSeaMetadataSerializationStrategy() + return strategy.serializeResource(nft) + } + } + return nil +} diff --git a/cadence/tests/Serialize_tests.cdc b/cadence/tests/Serialize_tests.cdc index 3a7ad0f5..cdfd30fb 100644 --- a/cadence/tests/Serialize_tests.cdc +++ b/cadence/tests/Serialize_tests.cdc @@ -1,14 +1,67 @@ import Test import BlockchainHelpers +import "NonFungibleToken" +import "ViewResolver" +import "MetadataViews" + import "Serialize" +import "SerializationInterfaces" access(all) -let serializeAccount = Test.getAccount(0x0000000000000007) +let admin = Test.getAccount(0x0000000000000007) +access(all) +let alice = Test.createAccount() + +// access(all) +// let testSerializableStructOutput = "{\"trait_type\": \"Name\", \"value\": \"TestSerializableStruct\"}" + +// access(all) +// struct TestSerializableStruct : SerializationInterfaces.SerializableStruct { +// access(all) +// fun serialize(): String { +// return testSerializableStructOutput +// } +// } access(all) fun setup() { var err = Test.deployContract( + name: "ViewResolver", + path: "../contracts/standards/ViewResolver.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "Burner", + path: "../contracts/standards/Burner.cdc", + arguments: [] + ) + err = Test.deployContract( + name: "FungibleToken", + path: "../contracts/standards/FungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "NonFungibleToken", + path: "../contracts/standards/NonFungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "MetadataViews", + path: "../contracts/standards/MetadataViews.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "SerializationInterfaces", + path: "../contracts/utils/SerializationInterfaces.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( name: "Serialize", path: "../contracts/utils/Serialize.cdc", arguments: [] @@ -184,37 +237,43 @@ fun testBoolTryToJSONStringSucceeds() { Test.assertEqual(expectedFalse, actualFalse!) } -access(all) -fun testBoolToStringSucceeds() { - let t: Bool = true - let f: Bool = false - - let expectedTrue = "true" - let expectedFalse = "false" - - var actualTrue = Serialize.boolToString(t) - var actualFalse = Serialize.boolToString(f) - - Test.assertEqual(expectedTrue, actualTrue) - Test.assertEqual(expectedFalse, actualFalse) -} - access(all) fun testArrayToJSONStringSucceeds() { let arr: [AnyStruct] = [ - 127, - 255, - "Hello, World!", - "c", - Address(0x0000000000000007), - UFix64.max, - true - ] + 127, + 255, + "Hello, World!", + "c", + Address(0x0000000000000007), + UFix64.max, + true + ] let expected = "[\"127\", \"255\", \"Hello, World!\", \"c\", \"0x0000000000000007\", \"184467440737.09551615\", \"true\"]" - var actual = Serialize.arrayToString(arr) + var actual = Serialize.arrayToJSONString(arr) Test.assertEqual(expected, actual!) } +access(all) +fun testDictToJSONStringSucceeds() { + let dict: {String: AnyStruct} = { + "bool": true, + "arr": [ 127, "Hello, World!" ] + } + + // Mapping values can be indexed in arbitrary order, so we need to check for all possible outputs + var expectedOne: String = "{\"bool\": \"true\", \"arr\": [\"127\", \"Hello, World!\"]}" + var expectedTwo: String = "{\"arr\": [\"127\", \"Hello, World!\"], \"bool\": \"true\"}" + + var actual: String? = Serialize.dictToJSONString(dict: dict, excludedNames: nil) + Test.assertEqual(true, expectedOne == actual! || expectedTwo == actual!) + + actual = Serialize.tryToJSONString(dict) + Test.assertEqual(true, expectedOne == actual! || expectedTwo == actual!) + + actual = Serialize.dictToJSONString(dict: dict, excludedNames: ["bool"]) + expectedOne = "{\"arr\": [\"127\", \"Hello, World!\"]}" + Test.assertEqual(true, expectedOne == actual!) +} diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc new file mode 100644 index 00000000..a9291169 --- /dev/null +++ b/cadence/tests/serialize_nft_tests.cdc @@ -0,0 +1,130 @@ +import Test +import BlockchainHelpers + +import "NonFungibleToken" +import "ViewResolver" +import "MetadataViews" + +import "Serialize" +import "SerializationInterfaces" + +access(all) +let admin = Test.getAccount(0x0000000000000007) +access(all) +let alice = Test.createAccount() + +access(all) +fun setup() { + var err = Test.deployContract( + name: "ViewResolver", + path: "../contracts/standards/ViewResolver.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "Burner", + path: "../contracts/standards/Burner.cdc", + arguments: [] + ) + err = Test.deployContract( + name: "FungibleToken", + path: "../contracts/standards/FungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "NonFungibleToken", + path: "../contracts/standards/NonFungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "MetadataViews", + path: "../contracts/standards/MetadataViews.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "ExampleNFT", + path: "../contracts/example-assets/ExampleNFT.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "SerializationInterfaces", + path: "../contracts/utils/SerializationInterfaces.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "Serialize", + path: "../contracts/utils/Serialize.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "SerializeNFT", + path: "../contracts/utils/SerializeNFT.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) +} + +access(all) +fun testSerializeNFTSucceeds() { + let setupResult = executeTransaction( + "../transactions/example-assets/setup_collection.cdc", + [], + alice + ) + Test.expect(setupResult, Test.beSucceeded()) + + let mintResult = executeTransaction( + "../transactions/example-assets/mint_nft.cdc", + [alice.address, "ExampleNFT", "Example NFT Collection", "https://flow.com/examplenft.jpg", [], [], []], + admin + ) + Test.expect(mintResult, Test.beSucceeded()) + + let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " + let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"54\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}" + let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"54\"}" + + let idsResult = executeScript( + "../scripts/nft/get_ids.cdc", + [alice.address, "cadenceExampleNFTCollection"] + ) + Test.expect(idsResult, Test.beSucceeded()) + let ids = idsResult.returnValue! as! [UInt64] + + let serializeMetadataResult = executeScript( + "../scripts/serialize/serialize_nft.cdc", + [alice.address, "cadenceExampleNFTCollection", ids[0]] + ) + Test.expect(serializeMetadataResult, Test.beSucceeded()) + + let serializedMetadata = serializeMetadataResult.returnValue! as! String + + Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) + // Test.assertEqual(serializedMetadata, expectedPrefix.concat(altSuffix1)) +} + +access(all) +fun testOpenSeaMetadataSerializationStrategySucceeds() { + let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " + let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"54\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}" + let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"54\"}" + + let idsResult = executeScript( + "../scripts/nft/get_ids.cdc", + [alice.address, "cadenceExampleNFTCollection"] + ) + Test.expect(idsResult, Test.beSucceeded()) + let ids = idsResult.returnValue! as! [UInt64] + + let serializeMetadataResult = executeScript( + "../scripts/serialize/serialize_nft_from_open_sea_strategy.cdc", + [alice.address, "cadenceExampleNFTCollection", ids[0]] + ) + Test.expect(serializeMetadataResult, Test.beSucceeded()) +} diff --git a/flow.json b/flow.json index ff11de22..9b42a063 100644 --- a/flow.json +++ b/flow.json @@ -16,7 +16,8 @@ "source": "./cadence/contracts/standards/Burner.cdc", "aliases": { "emulator": "ee82856bf20e2aa6", - "previewnet": "b6763b4399a888c8" + "previewnet": "b6763b4399a888c8", + "testing": "0000000000000007" } }, "CrossVMNFT": { @@ -41,7 +42,8 @@ "ExampleNFT": { "source": "./cadence/contracts/example-assets/ExampleNFT.cdc", "aliases": { - "emulator": "179b6b1cb6755e31" + "emulator": "179b6b1cb6755e31", + "testing": "0000000000000007" } }, "FlowEVMBridge": { @@ -89,6 +91,7 @@ "emulator": "ee82856bf20e2aa6", "mainnet": "f233dcee88fe0abe", "previewnet": "a0225e7000ac82a9", + "testing": "0000000000000007", "testnet": "9a0766d93b6608b7" } }, @@ -98,6 +101,7 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "f233dcee88fe0abe", "previewnet": "a0225e7000ac82a9", + "testing": "0000000000000007", "testnet": "9a0766d93b6608b7" } }, @@ -125,6 +129,7 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", + "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } }, @@ -134,6 +139,7 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", + "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } }, @@ -150,6 +156,20 @@ "testing": "0000000000000007" } }, + "SerializeNFT": { + "source": "./cadence/contracts/utils/SerializeNFT.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, + "SerializationInterfaces": { + "source": "./cadence/contracts/utils/SerializationInterfaces.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, "StringUtils": { "source": "./cadence/contracts/utils/StringUtils.cdc", "aliases": { @@ -162,6 +182,7 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", + "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } } From 874f97f6a54d90a554f32b44f9e5f879be5a30d7 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:24:52 -0500 Subject: [PATCH 08/39] update foundry ci workflow --- .github/workflows/{test.yml => foundry_test.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{test.yml => foundry_test.yml} (96%) diff --git a/.github/workflows/test.yml b/.github/workflows/foundry_test.yml similarity index 96% rename from .github/workflows/test.yml rename to .github/workflows/foundry_test.yml index 9282e829..6e514359 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/foundry_test.yml @@ -1,6 +1,6 @@ name: test -on: workflow_dispatch +on: pull_request env: FOUNDRY_PROFILE: ci From 64e36c1e5b2ed74fd60b4d3c012a858b32c25e77 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:33:09 -0500 Subject: [PATCH 09/39] add Cadence tests to CI workflow --- .github/workflows/cadence_test.yml | 39 ++++++++++++++++++++++++++++++ local/normalize_coverage_report.sh | 3 +++ local/run_cadence_tests.sh | 1 + 3 files changed, 43 insertions(+) create mode 100644 .github/workflows/cadence_test.yml create mode 100644 local/normalize_coverage_report.sh create mode 100644 local/run_cadence_tests.sh diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml new file mode 100644 index 00000000..fee3a807 --- /dev/null +++ b/.github/workflows/cadence_test.yml @@ -0,0 +1,39 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + tests: + name: Flow CLI Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.20.x' + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Install Flow CLI + run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)" + - name: Flow CLI Version + run: flow version + - name: Update PATH + run: echo "/root/.local/bin" >> $GITHUB_PATH + - name: Run tests + run: sh local/run_cadence_tests.sh + - name: Normalize coverage report filepaths + run : sh ./local/normalize_coverage_report.sh + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + \ No newline at end of file diff --git a/local/normalize_coverage_report.sh b/local/normalize_coverage_report.sh new file mode 100644 index 00000000..8de7ee5f --- /dev/null +++ b/local/normalize_coverage_report.sh @@ -0,0 +1,3 @@ +sed -i 's/A.0000000000000007.SerializationInterfaces/cadence\contracts\/SerializationInterfaces.cdc/' coverage.lcov +sed -i 's/A.0000000000000007.Serialize/cadence\/contracts\/utils\/Serialize.cdc/' coverage.lcov +sed -i 's/A.0000000000000007.SerializeNFT/cadence\contracts\/SerializeNFT.cdc/' coverage.lcov \ No newline at end of file diff --git a/local/run_cadence_tests.sh b/local/run_cadence_tests.sh new file mode 100644 index 00000000..94e3a833 --- /dev/null +++ b/local/run_cadence_tests.sh @@ -0,0 +1 @@ +flow-c1 test --cover --covercode="contracts" --coverprofile="coverage.lcov" cadence/tests/*_tests.cdc \ No newline at end of file From 38b87f72c492b2137709a98d8cfc26b0bdf19ff8 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:37:51 -0500 Subject: [PATCH 10/39] update Cadence tests to run on PR --- .github/workflows/cadence_test.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml index fee3a807..0839697c 100644 --- a/.github/workflows/cadence_test.yml +++ b/.github/workflows/cadence_test.yml @@ -1,10 +1,6 @@ name: CI -on: - pull_request: - branches: [main] - push: - branches: [main] +on: pull_request jobs: tests: From 54bc3eac6784ed761276b1b3963fac0b52c7986e Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:46:05 -0500 Subject: [PATCH 11/39] update Flow CLI version used for CI --- .github/workflows/cadence_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml index 0839697c..69caf3c9 100644 --- a/.github/workflows/cadence_test.yml +++ b/.github/workflows/cadence_test.yml @@ -19,7 +19,7 @@ jobs: restore-keys: | ${{ runner.os }}-go- - name: Install Flow CLI - run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)" + run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.12.0-cadence-v1.0.0-M8-2 - name: Flow CLI Version run: flow version - name: Update PATH From 2ebe123abf14ebafee32c9392fd3524f7831a81e Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:47:19 -0500 Subject: [PATCH 12/39] fix test script command --- local/run_cadence_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/run_cadence_tests.sh b/local/run_cadence_tests.sh index 94e3a833..29da3dbb 100644 --- a/local/run_cadence_tests.sh +++ b/local/run_cadence_tests.sh @@ -1 +1 @@ -flow-c1 test --cover --covercode="contracts" --coverprofile="coverage.lcov" cadence/tests/*_tests.cdc \ No newline at end of file +flow test --cover --covercode="contracts" --coverprofile="coverage.lcov" cadence/tests/*_tests.cdc \ No newline at end of file From 7aa72ee1274d5a4b6c3204a90955e15b3d6ac810 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:15:57 -0500 Subject: [PATCH 13/39] add NFT serialization into bridge to EVM --- cadence/args/deploy-factory-args.json | 2 +- cadence/contracts/bridge/FlowEVMBridge.cdc | 34 ++++++++++++++++------ solidity/src/FlowBridgedERC721.sol | 4 +++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/cadence/args/deploy-factory-args.json b/cadence/args/deploy-factory-args.json index 9b27592d..d49bf2f5 100644 --- a/cadence/args/deploy-factory-args.json +++ b/cadence/args/deploy-factory-args.json @@ -1,7 +1,7 @@ [ { "type": "String", - "value": "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61255c806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611a1f8062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001a1f38038062001a1f833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b506008620000a0848262000386565b506009620000af838262000386565b50600a620000be828262000386565b5050505050505062000452565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6115bd80620004626000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80638da5cb5b116100de578063b49bbd9411610097578063cd279c7c11610071578063cd279c7c1461030f578063e8a3d48514610322578063e985e9c51461032a578063f2fde38b1461033d57600080fd5b8063b49bbd94146102e1578063b88d4fde146102e9578063c87b56dd146102fc57600080fd5b80638da5cb5b1461029d57806394e29329146102ae57806395d89b41146102b6578063a159047b146102be578063a22cb465146102c6578063a76b4d56146102d957600080fd5b806342966c681161013057806342966c681461021b5780634f558e791461022e5780635e0a9661146102595780636352211e1461026157806370a0823114610274578063715018a61461029557600080fd5b806301ffc9a71461017857806306fdde03146101a0578063081812fc146101b5578063095ea7b3146101e057806323b872dd146101f557806342842e0e14610208575b600080fd5b61018b61018636600461109c565b610350565b60405190151581526020015b60405180910390f35b6101a8610361565b6040516101979190611109565b6101c86101c336600461111c565b6103f3565b6040516001600160a01b039091168152602001610197565b6101f36101ee366004611151565b61041c565b005b6101f361020336600461117b565b61042b565b6101f361021636600461117b565b6104bb565b6101f361022936600461111c565b6104db565b61018b61023c36600461111c565b6000908152600260205260409020546001600160a01b0316151590565b6101a86104e7565b6101c861026f36600461111c565b6104f6565b6102876102823660046111b7565b610501565b604051908152602001610197565b6101f3610549565b6007546001600160a01b03166101c8565b6101a861055d565b6101a861056c565b6101a861057b565b6101f36102d43660046111d2565b610609565b6101a8610614565b6101a8610621565b6101f36102f736600461129a565b61062e565b6101a861030a36600461111c565b610645565b6101f361031d366004611316565b610650565b6101a861066c565b61018b610338366004611381565b61067b565b6101f361034b3660046111b7565b6106a9565b600061035b826106e7565b92915050565b606060008054610370906113b4565b80601f016020809104026020016040519081016040528092919081815260200182805461039c906113b4565b80156103e95780601f106103be576101008083540402835291602001916103e9565b820191906000526020600020905b8154815290600101906020018083116103cc57829003601f168201915b5050505050905090565b60006103fe8261070c565b506000828152600460205260409020546001600160a01b031661035b565b610427828233610745565b5050565b6001600160a01b03821661045a57604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610467838333610752565b9050836001600160a01b0316816001600160a01b0316146104b5576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610451565b50505050565b6104d68383836040518060200160405280600081525061062e565b505050565b61042760008233610752565b606060098054610370906113b4565b600061035b8261070c565b60006001600160a01b03821661052d576040516322718ad960e21b815260006004820152602401610451565b506001600160a01b031660009081526003602052604090205490565b61055161084b565b61055b6000610878565b565b606060088054610370906113b4565b606060018054610370906113b4565b60098054610588906113b4565b80601f01602080910402602001604051908101604052809291908181526020018280546105b4906113b4565b80156106015780601f106105d657610100808354040283529160200191610601565b820191906000526020600020905b8154815290600101906020018083116105e457829003601f168201915b505050505081565b6104273383836108ca565b600a8054610588906113b4565b60088054610588906113b4565b61063984848461042b565b6104b584848484610969565b606061035b82610a92565b61065861084b565b6106628383610ba3565b6104d68282610bbd565b6060600a8054610370906113b4565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6106b161084b565b6001600160a01b0381166106db57604051631e4fbdf760e01b815260006004820152602401610451565b6106e481610878565b50565b60006001600160e01b03198216632483248360e11b148061035b575061035b82610c0d565b6000818152600260205260408120546001600160a01b03168061035b57604051637e27328960e01b815260048101849052602401610451565b6104d68383836001610c5d565b6000828152600260205260408120546001600160a01b039081169083161561077f5761077f818486610d63565b6001600160a01b038116156107bd5761079c600085600080610c5d565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b038516156107ec576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6007546001600160a01b0316331461055b5760405163118cdaa760e01b8152336004820152602401610451565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166108fc57604051630b61174360e31b81526001600160a01b0383166004820152602401610451565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156104b557604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906109ab9033908890879087906004016113ee565b6020604051808303816000875af19250505080156109e6575060408051601f3d908101601f191682019092526109e39181019061142b565b60015b610a4f573d808015610a14576040519150601f19603f3d011682016040523d82523d6000602084013e610a19565b606091505b508051600003610a4757604051633250574960e11b81526001600160a01b0385166004820152602401610451565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610a8b57604051633250574960e11b81526001600160a01b0385166004820152602401610451565b5050505050565b6060610a9d8261070c565b5060008281526006602052604081208054610ab7906113b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae3906113b4565b8015610b305780601f10610b0557610100808354040283529160200191610b30565b820191906000526020600020905b815481529060010190602001808311610b1357829003601f168201915b505050505090506000610b4e60408051602081019091526000815290565b90508051600003610b60575092915050565b815115610b92578082604051602001610b7a929190611448565b60405160208183030381529060405292505050919050565b610b9b84610dc7565b949350505050565b610427828260405180602001604052806000815250610e3c565b6000828152600660205260409020610bd582826114c7565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b60006001600160e01b031982166380ac58cd60e01b1480610c3e57506001600160e01b03198216635b5e139f60e01b145b8061035b57506301ffc9a760e01b6001600160e01b031983161461035b565b8080610c7157506001600160a01b03821615155b15610d33576000610c818461070c565b90506001600160a01b03831615801590610cad5750826001600160a01b0316816001600160a01b031614155b8015610cc05750610cbe818461067b565b155b15610ce95760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610451565b8115610d315783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b610d6e838383610e53565b6104d6576001600160a01b038316610d9c57604051637e27328960e01b815260048101829052602401610451565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610451565b6060610dd28261070c565b506000610dea60408051602081019091526000815290565b90506000815111610e0a5760405180602001604052806000815250610e35565b80610e1484610eb6565b604051602001610e25929190611448565b6040516020818303038152906040525b9392505050565b610e468383610f49565b6104d66000848484610969565b60006001600160a01b03831615801590610b9b5750826001600160a01b0316846001600160a01b03161480610e8d5750610e8d848461067b565b80610b9b5750506000908152600460205260409020546001600160a01b03908116911614919050565b60606000610ec383610fae565b600101905060008167ffffffffffffffff811115610ee357610ee361120e565b6040519080825280601f01601f191660200182016040528015610f0d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610f1757509392505050565b6001600160a01b038216610f7357604051633250574960e11b815260006004820152602401610451565b6000610f8183836000610752565b90506001600160a01b038116156104d6576040516339e3563760e11b815260006004820152602401610451565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610fed5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611019576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061103757662386f26fc10000830492506010015b6305f5e100831061104f576305f5e100830492506008015b612710831061106357612710830492506004015b60648310611075576064830492506002015b600a831061035b5760010192915050565b6001600160e01b0319811681146106e457600080fd5b6000602082840312156110ae57600080fd5b8135610e3581611086565b60005b838110156110d45781810151838201526020016110bc565b50506000910152565b600081518084526110f58160208601602086016110b9565b601f01601f19169290920160200192915050565b602081526000610e3560208301846110dd565b60006020828403121561112e57600080fd5b5035919050565b80356001600160a01b038116811461114c57600080fd5b919050565b6000806040838503121561116457600080fd5b61116d83611135565b946020939093013593505050565b60008060006060848603121561119057600080fd5b61119984611135565b92506111a760208501611135565b9150604084013590509250925092565b6000602082840312156111c957600080fd5b610e3582611135565b600080604083850312156111e557600080fd5b6111ee83611135565b91506020830135801515811461120357600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561123f5761123f61120e565b604051601f8501601f19908116603f011681019082821181831017156112675761126761120e565b8160405280935085815286868601111561128057600080fd5b858560208301376000602087830101525050509392505050565b600080600080608085870312156112b057600080fd5b6112b985611135565b93506112c760208601611135565b925060408501359150606085013567ffffffffffffffff8111156112ea57600080fd5b8501601f810187136112fb57600080fd5b61130a87823560208401611224565b91505092959194509250565b60008060006060848603121561132b57600080fd5b61133484611135565b925060208401359150604084013567ffffffffffffffff81111561135757600080fd5b8401601f8101861361136857600080fd5b61137786823560208401611224565b9150509250925092565b6000806040838503121561139457600080fd5b61139d83611135565b91506113ab60208401611135565b90509250929050565b600181811c908216806113c857607f821691505b6020821081036113e857634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611421908301846110dd565b9695505050505050565b60006020828403121561143d57600080fd5b8151610e3581611086565b6000835161145a8184602088016110b9565b83519083019061146e8183602088016110b9565b01949350505050565b601f8211156104d6576000816000526020600020601f850160051c810160208610156114a05750805b601f850160051c820191505b818110156114bf578281556001016114ac565b505050505050565b815167ffffffffffffffff8111156114e1576114e161120e565b6114f5816114ef84546113b4565b84611477565b602080601f83116001811461152a57600084156115125750858301515b600019600386901b1c1916600185901b1785556114bf565b600085815260208120601f198616915b828110156115595788860151825594840194600190910190840161153a565b50858210156115775787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212200a956fe468b09a46bc7a03d4becd5721b90561dd1417ed9a36008af773946ad764736f6c63430008170033a26469706673582212209c26a1468da9c564746b513a99be6d96c5f2951e2ee06e1cdfc4889115eb44b664736f6c63430008170033" + "value": "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6129f4806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611eb78062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001eb738038062001eb7833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b50600c620000a0848262000386565b50600d620000af838262000386565b50600e620000be828262000386565b5050505050505062000452565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611a5580620004626000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a76b4d56116100a2578063cd279c7c11610071578063cd279c7c146103a8578063e8a3d485146103bb578063e985e9c5146103c3578063f2fde38b146103d657600080fd5b8063a76b4d5614610372578063b49bbd941461037a578063b88d4fde14610382578063c87b56dd1461039557600080fd5b806394e29329116100de57806394e293291461034757806395d89b411461034f578063a159047b14610357578063a22cb4651461035f57600080fd5b806370a082311461031b578063715018a61461032e5780638da5cb5b1461033657600080fd5b80632f745c59116101715780634f558e791161014b5780634f558e79146102c25780634f6ccce7146102ed5780635e0a9661146103005780636352211e1461030857600080fd5b80632f745c591461028957806342842e0e1461029c57806342966c68146102af57600080fd5b8063095ea7b3116101ad578063095ea7b31461023c57806318160ddd1461025157806318e97fd11461026357806323b872dd1461027657600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611494565b6103e9565b60405190151581526020015b60405180910390f35b6102046103fa565b6040516101f39190611501565b61022461021f366004611514565b61048c565b6040516001600160a01b0390911681526020016101f3565b61024f61024a366004611549565b6104b5565b005b6009545b6040519081526020016101f3565b61024f61027136600461161f565b6104c4565b61024f610284366004611666565b6104d6565b610255610297366004611549565b610566565b61024f6102aa366004611666565b6105cb565b61024f6102bd366004611514565b6105eb565b6101e76102d0366004611514565b6000908152600260205260409020546001600160a01b0316151590565b6102556102fb366004611514565b6105f7565b610204610650565b610224610316366004611514565b61065f565b6102556103293660046116a2565b61066a565b61024f6106b2565b600b546001600160a01b0316610224565b6102046106c6565b6102046106d5565b6102046106e4565b61024f61036d3660046116bd565b610772565b61020461077d565b61020461078a565b61024f6103903660046116f9565b610797565b6102046103a3366004611514565b6107ae565b61024f6103b6366004611775565b6107b9565b6102046107d5565b6101e76103d13660046117cc565b6107e4565b61024f6103e43660046116a2565b610812565b60006103f482610850565b92915050565b606060008054610409906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610435906117ff565b80156104825780601f1061045757610100808354040283529160200191610482565b820191906000526020600020905b81548152906001019060200180831161046557829003601f168201915b5050505050905090565b600061049782610875565b506000828152600460205260409020546001600160a01b03166103f4565b6104c08282336108ae565b5050565b6104cc6108bb565b6104c082826108e8565b6001600160a01b03821661050557604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610512838333610938565b9050836001600160a01b0316816001600160a01b031614610560576040516364283d7b60e01b81526001600160a01b03808616600483015260248201849052821660448201526064016104fc565b50505050565b60006105718361066a565b82106105a25760405163295f44f760e21b81526001600160a01b0384166004820152602481018390526044016104fc565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6105e683838360405180602001604052806000815250610797565b505050565b6104c060008233610938565b600061060260095490565b821061062b5760405163295f44f760e21b815260006004820152602481018390526044016104fc565b6009828154811061063e5761063e611839565b90600052602060002001549050919050565b6060600d8054610409906117ff565b60006103f482610875565b60006001600160a01b038216610696576040516322718ad960e21b8152600060048201526024016104fc565b506001600160a01b031660009081526003602052604090205490565b6106ba6108bb565b6106c4600061094d565b565b6060600c8054610409906117ff565b606060018054610409906117ff565b600d80546106f1906117ff565b80601f016020809104026020016040519081016040528092919081815260200182805461071d906117ff565b801561076a5780601f1061073f5761010080835404028352916020019161076a565b820191906000526020600020905b81548152906001019060200180831161074d57829003601f168201915b505050505081565b6104c033838361099f565b600e80546106f1906117ff565b600c80546106f1906117ff565b6107a28484846104d6565b61056084848484610a3e565b60606103f482610b67565b6107c16108bb565b6107cb8383610c70565b6105e682826108e8565b6060600e8054610409906117ff565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61081a6108bb565b6001600160a01b03811661084457604051631e4fbdf760e01b8152600060048201526024016104fc565b61084d8161094d565b50565b60006001600160e01b0319821663780e9d6360e01b14806103f457506103f482610c8a565b6000818152600260205260408120546001600160a01b0316806103f457604051637e27328960e01b8152600481018490526024016104fc565b6105e68383836001610caf565b600b546001600160a01b031633146106c45760405163118cdaa760e01b81523360048201526024016104fc565b6000828152600660205260409020610900828261189f565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6000610945848484610db5565b949350505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166109d157604051630b61174360e31b81526001600160a01b03831660048201526024016104fc565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561056057604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610a8090339088908790879060040161195f565b6020604051808303816000875af1925050508015610abb575060408051601f3d908101601f19168201909252610ab89181019061199c565b60015b610b24573d808015610ae9576040519150601f19603f3d011682016040523d82523d6000602084013e610aee565b606091505b508051600003610b1c57604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610b6057604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b5050505050565b6060610b7282610875565b5060008281526006602052604081208054610b8c906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb8906117ff565b8015610c055780601f10610bda57610100808354040283529160200191610c05565b820191906000526020600020905b815481529060010190602001808311610be857829003601f168201915b505050505090506000610c2360408051602081019091526000815290565b90508051600003610c35575092915050565b815115610c67578082604051602001610c4f9291906119b9565b60405160208183030381529060405292505050919050565b61094584610e82565b6104c0828260405180602001604052806000815250610ef7565b60006001600160e01b03198216632483248360e11b14806103f457506103f482610f0e565b8080610cc357506001600160a01b03821615155b15610d85576000610cd384610875565b90506001600160a01b03831615801590610cff5750826001600160a01b0316816001600160a01b031614155b8015610d125750610d1081846107e4565b155b15610d3b5760405163a9fbf51f60e01b81526001600160a01b03841660048201526024016104fc565b8115610d835783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610dc3858585610f5e565b90506001600160a01b038116610e2057610e1b84600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b610e43565b846001600160a01b0316816001600160a01b031614610e4357610e438185611057565b6001600160a01b038516610e5f57610e5a846110e8565b610945565b846001600160a01b0316816001600160a01b031614610945576109458585611197565b6060610e8d82610875565b506000610ea560408051602081019091526000815290565b90506000815111610ec55760405180602001604052806000815250610ef0565b80610ecf846111e7565b604051602001610ee09291906119b9565b6040516020818303038152906040525b9392505050565b610f01838361127a565b6105e66000848484610a3e565b60006001600160e01b031982166380ac58cd60e01b1480610f3f57506001600160e01b03198216635b5e139f60e01b145b806103f457506301ffc9a760e01b6001600160e01b03198316146103f4565b6000828152600260205260408120546001600160a01b0390811690831615610f8b57610f8b8184866112df565b6001600160a01b03811615610fc957610fa8600085600080610caf565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615610ff8576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006110628361066a565b6000838152600860205260409020549091508082146110b5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009546000906110fa906001906119e8565b6000838152600a60205260408120546009805493945090928490811061112257611122611839565b90600052602060002001549050806009838154811061114357611143611839565b6000918252602080832090910192909255828152600a9091526040808220849055858252812055600980548061117b5761117b611a09565b6001900381819060005260206000200160009055905550505050565b600060016111a48461066a565b6111ae91906119e8565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b606060006111f483611343565b600101905060008167ffffffffffffffff81111561121457611214611573565b6040519080825280601f01601f19166020018201604052801561123e576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461124857509392505050565b6001600160a01b0382166112a457604051633250574960e11b8152600060048201526024016104fc565b60006112b283836000610938565b90506001600160a01b038116156105e6576040516339e3563760e11b8152600060048201526024016104fc565b6112ea83838361141b565b6105e6576001600160a01b03831661131857604051637e27328960e01b8152600481018290526024016104fc565b60405163177e802f60e01b81526001600160a01b0383166004820152602481018290526044016104fc565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113825772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113ae576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113cc57662386f26fc10000830492506010015b6305f5e10083106113e4576305f5e100830492506008015b61271083106113f857612710830492506004015b6064831061140a576064830492506002015b600a83106103f45760010192915050565b60006001600160a01b038316158015906109455750826001600160a01b0316846001600160a01b03161480611455575061145584846107e4565b806109455750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461084d57600080fd5b6000602082840312156114a657600080fd5b8135610ef08161147e565b60005b838110156114cc5781810151838201526020016114b4565b50506000910152565b600081518084526114ed8160208601602086016114b1565b601f01601f19169290920160200192915050565b602081526000610ef060208301846114d5565b60006020828403121561152657600080fd5b5035919050565b80356001600160a01b038116811461154457600080fd5b919050565b6000806040838503121561155c57600080fd5b6115658361152d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156115a4576115a4611573565b604051601f8501601f19908116603f011681019082821181831017156115cc576115cc611573565b816040528093508581528686860111156115e557600080fd5b858560208301376000602087830101525050509392505050565b600082601f83011261161057600080fd5b610ef083833560208501611589565b6000806040838503121561163257600080fd5b82359150602083013567ffffffffffffffff81111561165057600080fd5b61165c858286016115ff565b9150509250929050565b60008060006060848603121561167b57600080fd5b6116848461152d565b92506116926020850161152d565b9150604084013590509250925092565b6000602082840312156116b457600080fd5b610ef08261152d565b600080604083850312156116d057600080fd5b6116d98361152d565b9150602083013580151581146116ee57600080fd5b809150509250929050565b6000806000806080858703121561170f57600080fd5b6117188561152d565b93506117266020860161152d565b925060408501359150606085013567ffffffffffffffff81111561174957600080fd5b8501601f8101871361175a57600080fd5b61176987823560208401611589565b91505092959194509250565b60008060006060848603121561178a57600080fd5b6117938461152d565b925060208401359150604084013567ffffffffffffffff8111156117b657600080fd5b6117c2868287016115ff565b9150509250925092565b600080604083850312156117df57600080fd5b6117e88361152d565b91506117f66020840161152d565b90509250929050565b600181811c9082168061181357607f821691505b60208210810361183357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f8211156105e6576000816000526020600020601f850160051c810160208610156118785750805b601f850160051c820191505b8181101561189757828155600101611884565b505050505050565b815167ffffffffffffffff8111156118b9576118b9611573565b6118cd816118c784546117ff565b8461184f565b602080601f83116001811461190257600084156118ea5750858301515b600019600386901b1c1916600185901b178555611897565b600085815260208120601f198616915b8281101561193157888601518255948401946001909101908401611912565b508582101561194f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611992908301846114d5565b9695505050505050565b6000602082840312156119ae57600080fd5b8151610ef08161147e565b600083516119cb8184602088016114b1565b8351908301906119df8183602088016114b1565b01949350505050565b818103818111156103f457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212206ff38700c73b602455dbb7964f2d3281f62efc77263f0f3bdb67f5e4ee5d4f3f64736f6c63430008170033a26469706673582212207f55223fc039b168a1e0c0bb9dc8d219b8219d1b2151fe8e9843aecefd41f82664736f6c63430008170033" }, { "type": "UInt64", diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index 70ce13da..ade1e789 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -15,6 +15,7 @@ import "FlowEVMBridgeConfig" import "FlowEVMBridgeUtils" import "FlowEVMBridgeNFTEscrow" import "FlowEVMBridgeTemplates" +import "SerializeNFT" /// The FlowEVMBridge contract is the main entrypoint for bridging NFT & FT assets between Flow & FlowEVM. /// @@ -135,11 +136,6 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { let tokenType = token.getType() let tokenID = token.id let evmID = CrossVMNFT.getEVMID(from: &token as &{NonFungibleToken.NFT}) ?? UInt256(token.id) - // Grab the URI from the NFT if available - var uri: String = "" - if let metadata = token.resolveView(Type()) as! CrossVMNFT.EVMBridgedMetadata? { - uri = metadata.uri.uri() - } // Lock the NFT & calculate the storage used by the NFT let storageUsed = FlowEVMBridgeNFTEscrow.lockNFT(<-token) @@ -159,6 +155,16 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { let isFactoryDeployed = FlowEVMBridgeUtils.isEVMContractBridgeOwned(evmContractAddress: associatedAddress) // Controlled by the bridge - mint or transfer based on existence if isFactoryDeployed { + // Grab the URI from the NFT if available + var uri: String = "" + // Default to project-specified URI + if let metadata = token.resolveView(Type()) as! CrossVMNFT.EVMBridgedMetadata? { + uri = metadata.uri.uri() + } else { + // Otherwise, serialize the NFT using OpenSea Metadata strategy + uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT}) + } + // Check if the ERC721 exists let existsResponse = EVM.decodeABI( types: [Type()], @@ -173,17 +179,27 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { assert(existsResponse.length == 1, message: "Invalid response length") let exists = existsResponse[0] as! Bool if exists { - // if so transfer - let callResult: EVM.Result = FlowEVMBridgeUtils.call( + // If so transfer + let transferResult: EVM.Result = FlowEVMBridgeUtils.call( signature: "safeTransferFrom(address,address,uint256)", targetEVMAddress: associatedAddress, args: [self.getBridgeCOAEVMAddress(), to, evmID], gasLimit: 15000000, value: 0.0 ) - assert(callResult.status == EVM.Status.successful, message: "Tranfer to bridge recipient failed") + assert(transferResult.status == EVM.Status.successful, message: "Tranfer to bridge recipient failed") + + // And update the URI to reflect current metadata + let updateURIResult: EVM.Result = FlowEVMBridgeUtils.call( + signature: "updateTokenURI(uint256,string)", + targetEVMAddress: associatedAddress, + args: [evmID, uri], + gasLimit: 15000000, + value: 0.0 + ) + assert(updateURIResult.status == EVM.Status.successful, message: "Tranfer to bridge recipient failed") } else { - // Otherwise mint + // Otherwise mint with current URI let callResult: EVM.Result = FlowEVMBridgeUtils.call( signature: "safeMint(address,uint256,string)", targetEVMAddress: associatedAddress, diff --git a/solidity/src/FlowBridgedERC721.sol b/solidity/src/FlowBridgedERC721.sol index d4dc4369..4742587c 100644 --- a/solidity/src/FlowBridgedERC721.sol +++ b/solidity/src/FlowBridgedERC721.sol @@ -30,6 +30,10 @@ contract FlowBridgedERC721 is ERC721, ERC721URIStorage, ERC721Burnable, ERC721En _setTokenURI(tokenId, uri); } + function updateTokenURI(uint256 tokenId, string memory uri) public onlyOwner { + _setTokenURI(tokenId, uri); + } + function contractURI() public view returns (string memory) { return contractMetadata; } From 8b2c6e17f592bf68134dd738a6b8e3572171b3e4 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:42:05 -0500 Subject: [PATCH 14/39] add metadata syncing on tokenURI when bridging from EVM to Cadence --- .../args/bridged-nft-code-chunks-args.json | 12 ++++-- cadence/contracts/bridge/FlowEVMBridge.cdc | 18 ++++++--- .../emulator/EVMBridgedNFTTemplate.cdc | 38 ++++++++++++++++--- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/cadence/args/bridged-nft-code-chunks-args.json b/cadence/args/bridged-nft-code-chunks-args.json index 0129757d..f451dd38 100644 --- a/cadence/args/bridged-nft-code-chunks-args.json +++ b/cadence/args/bridged-nft-code-chunks-args.json @@ -10,7 +10,7 @@ "value": "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078663864366530353836623061323063370a696d706f7274204d6574616461746156696577732066726f6d203078663864366530353836623061323063370a696d706f727420566965775265736f6c7665722066726f6d203078663864366530353836623061323063370a696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a696d706f727420466c6f77546f6b656e2066726f6d203078306165353363623665336634326137390a0a696d706f72742045564d2066726f6d203078663864366530353836623061323063370a0a696d706f7274204943726f7373564d2066726f6d203078663864366530353836623061323063370a696d706f7274204945564d4272696467654e46544d696e7465722066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467654e4654457363726f772066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d427269646765436f6e6669672066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467655574696c732066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467652066726f6d203078663864366530353836623061323063370a696d706f72742043726f7373564d4e46542066726f6d203078663864366530353836623061323063370a0a2f2f2f205468697320636f6e747261637420697320612074656d706c617465207573656420627920466c6f7745564d42726964676520746f20646566696e652045564d2d6e6174697665204e46547320627269646765642066726f6d20466c6f772045564d20746f20466c6f772e0a2f2f2f2055706f6e206465706c6f796d656e74206f66207468697320636f6e74726163742c2074686520636f6e7472616374206e616d65206973206465726976656420617320612066756e6374696f6e206f6620746865206173736574207479706520286865726520616e2045524337323120616b610a2f2f2f20616e204e46542920616e642074686520636f6e747261637427732045564d20616464726573732e20546865206465726976656420636f6e7472616374206e616d65206973207468656e206a6f696e65642077697468207468697320636f6e7472616374277320636f64652c0a2f2f2f207072657061726564206173206368756e6b7320696e20466c6f7745564d42726964676554656d706c61746573206265666f7265206265696e67206465706c6f79656420746f2074686520466c6f772045564d20427269646765206163636f756e742e0a2f2f2f0a2f2f2f204f6e206272696467696e672c2074686520455243373231206973207472616e7366657272656420746f2074686520627269646765277320436164656e63654f776e65644163636f756e742045564d206164647265737320616e642061206e6577204e4654206973206d696e7465642066726f6d0a2f2f2f207468697320636f6e747261637420746f20746865206272696467696e672063616c6c65722e204f6e2072657475726e20746f20466c6f772045564d2c2074686520726576657273652070726f6365737320697320666f6c6c6f776564202d2074686520746f6b656e206973206275726e65640a2f2f2f20696e207468697320636f6e747261637420616e642074686520455243373231206973207472616e7366657272656420746f2074686520646566696e656420726563697069656e742e20496e2074686973207761792c2074686520436164656e636520746f6b656e206163747320617320610a2f2f2f20726570726573656e746174696f6e206f6620626f7468207468652045564d204e465420616e642074687573206f776e6572736869702072696768747320746f2069742075706f6e206272696467696e67206261636b20746f20466c6f772045564d2e0a2f2f2f0a2f2f2f20546f20627269646765206265747765656e20564d732c20612063616c6c65722063616e20656974686572207573652074686520636f6e7472616374206d6574686f647320646566696e65642062656c6f772c206f72207573652074686520466c6f7745564d42726964676527730a2f2f2f206272696467696e67206d6574686f64732077686963682077696c6c2070726f6772616d61746963616c6c7920726f757465206272696467696e672063616c6c7320746f207468697320636f6e74726163742e0a2f2f2f0a2f2f20544f444f3a20496d706c656d656e74204e465420636f6e747261637420696e74657266616365206f6e636520763220617661696c61626c65206c6f63616c6c790a61636365737328616c6c2920636f6e747261637420" }, { "type": "String", - "value": "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f2054686520555249206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574207572693a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020207572693a20537472696e672c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e757269203d207572690a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e5552492873656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20" + "value": "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e5552492873656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20" }, { "type": "String", "value": "2e7265736f6c7665436f6e747261637456696577280a2020202020202020202020202020202020202020202020207265736f75726365547970653a2073656c662e6765745479706528292c0a20202020202020202020202020202020202020202020202076696577547970653a20547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020202020202072657475726e20" @@ -22,7 +22,13 @@ "value": "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a2073656c662e676574547970652829290a20202020202020207d0a0a20202020202020202f2a202d2d2d2043726f7373564d4e465420636f6e666f726d616e6365202d2d2d202a2f0a20202020202020202f2f0a20202020202020202f2f2f2052657475726e73207468652045564d20636f6e74726163742061646472657373206f6620746865204e46540a202020202020202061636365737328616c6c2920766965772066756e2067657445564d436f6e74726163744164647265737328293a2045564d2e45564d41646472657373207b0a20202020202020202020202072657475726e20" }, { "type": "String", - "value": "2e67657445564d436f6e74726163744164647265737328290a20202020202020207d0a0a20202020202020202f2f2f2053696d696c617220746f204552433732312e746f6b656e555249206d6574686f642c2072657475726e732074686520555249206f6620746865204e465420776974682073656c662e65766d49442061742074696d65206f66206272696467696e670a202020202020202061636365737328616c6c2920766965772066756e20746f6b656e55524928293a20537472696e67207b0a20202020202020202020202072657475726e2073656c662e7572690a20202020202020207d0a202020207d0a0a202020202f2f2f2054686973207265736f7572636520686f6c6473206173736f636961746564204e4654732c20616e642073657276657320717565726965732061626f75742073746f726564204e4654730a2020202061636365737328616c6c29207265736f7572636520436f6c6c656374696f6e3a204e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e2c2043726f7373564d4e46542e45564d4e4654436f6c6c656374696f6e207b0a20202020202020202f2f2f2064696374696f6e617279206f66204e465420636f6e666f726d696e6720746f6b656e7320696e6465786564206f6e2074686569722049440a202020202020202061636365737328636f6e74726163742920766172206f776e65644e4654733a20407b55496e7436343a20" + "value": "2e67657445564d436f6e74726163744164647265737328290a20202020202020207d0a0a20202020202020202f2f2f2053696d696c617220746f204552433732312e746f6b656e555249206d6574686f642c2072657475726e732074686520555249206f6620746865204e465420776974682073656c662e65766d49442061742074696d65206f66206272696467696e670a202020202020202061636365737328616c6c2920766965772066756e20746f6b656e55524928293a20537472696e67207b0a20202020202020202020202072657475726e20" + }, { + "type": "String", + "value": "2e746f6b656e555249735b73656c662e65766d49445d203f3f2022220a20202020202020207d0a0a20202020202020202f2a202d2d2d20427269646765206f6e6c79206d6574686f64202d2d2d202a2f0a20202020202020202f2f0a20202020202020202f2f2f20416c6c6f7773207468652062726964676520746f20757064617465207468652055524920616761696e73742074686520736f757263652045524337323120636f6e7472616374206f6e206272696467696e67206261636b20746f20436164656e63650a2020202020202020616363657373286163636f756e74290a202020202020202066756e20757064617465555249285f206e65773a20537472696e6729207b0a202020202020202020202020" + }, { + "type": "String", + "value": "2e757064617465546f6b656e5552492869643a2073656c662e65766d49442c206e65775552493a206e6577290a20202020202020207d0a202020207d0a0a202020202f2f2f2054686973207265736f7572636520686f6c6473206173736f636961746564204e4654732c20616e642073657276657320717565726965732061626f75742073746f726564204e4654730a2020202061636365737328616c6c29207265736f7572636520436f6c6c656374696f6e3a204e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e2c2043726f7373564d4e46542e45564d4e4654436f6c6c656374696f6e207b0a20202020202020202f2f2f2064696374696f6e617279206f66204e465420636f6e666f726d696e6720746f6b656e7320696e6465786564206f6e2074686569722049440a202020202020202061636365737328636f6e74726163742920766172206f776e65644e4654733a20407b55496e7436343a20" }, { "type": "String", "value": "2e4e46547d0a20202020202020202f2f2f204d617070696e67206f662045564d2049447320746f20466c6f77204e4654204944730a202020202020202061636365737328636f6e747261637429206c65742065766d4944546f466c6f7749443a207b55496e743235363a2055496e7436347d0a0a202020202020202061636365737328616c6c29207661722073746f72616765506174683a2053746f72616765506174680a202020202020202061636365737328616c6c2920766172207075626c6963506174683a205075626c6963506174680a0a2020202020202020696e6974202829207b0a20202020202020202020202073656c662e6f776e65644e465473203c2d207b7d0a20202020202020202020202073656c662e65766d4944546f466c6f774944203d207b7d0a2020202020202020202020206c657420636f6c6c656374696f6e44617461203d20" @@ -67,7 +73,7 @@ "value": "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a20547970653c40" }, { "type": "String", - "value": "2e4e46543e2829290a20202020202020202020202020202020202020207d290a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e20636f6c6c656374696f6e446174610a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020206c6574206d65646961203d204d6574616461746156696577732e4d65646961280a202020202020202020202020202020202020202066696c653a204d6574616461746156696577732e4854545046696c65280a20202020202020202020202020202020202020202020202075726c3a202268747470733a2f2f6173736574732e776562736974652d66696c65732e636f6d2f3566363239346330633761386364643634336231633832302f3566363239346330633761386364613535636231633933365f466c6f775f576f72646d61726b2e737667220a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206d65646961547970653a2022696d6167652f7376672b786d6c220a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e204d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c6179280a20202020202020202020202020202020202020206e616d653a202254686520466c6f77564d2042726964676564204e465420436f6c6c656374696f6e222c0a20202020202020202020202020202020202020206465736372697074696f6e3a20225468697320636f6c6c656374696f6e2077617320627269646765642066726f6d20466c6f772045564d2e222c0a202020202020202020202020202020202020202065787465726e616c55524c3a204d6574616461746156696577732e45787465726e616c55524c282268747470733a2f2f6272696467652e666c6f772e636f6d2f6e667422292c0a2020202020202020202020202020202020202020737175617265496d6167653a206d656469612c0a202020202020202020202020202020202020202062616e6e6572496d6167653a206d656469612c0a2020202020202020202020202020202020202020736f6369616c733a207b7d0a20202020202020202020202020202020290a2020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a2020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a20202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202020202020202020207572693a2073656c662e636f6e747261637455524920213d206e696c203f2043726f7373564d4e46542e5552492873656c662e636f6e74726163745552492129203a2043726f7373564d4e46542e555249282222290a20202020202020202020202020202020290a20202020202020207d0a202020202020202072657475726e206e696c0a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a2020202020202020496e7465726e616c204d6574686f64730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f0a20202020616363657373286163636f756e74290a2020202066756e206d696e744e46542869643a2055496e743235362c20746f6b656e5552493a20537472696e67293a20404e4654207b0a202020202020202072657475726e203c2d637265617465204e4654280a2020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202065766d49443a2069642c0a2020202020202020202020207572693a20746f6b656e5552492c0a2020202020202020202020206d657461646174613a207b0a20202020202020202020202020202020224272696467656420426c6f636b223a2067657443757272656e74426c6f636b28292e6865696768742c0a2020202020202020202020202020202022427269646765642054696d657374616d70223a2067657443757272656e74426c6f636b28292e74696d657374616d700a2020202020202020202020207d0a2020202020202020290a202020207d0a0a20202020696e6974286e616d653a20537472696e672c2073796d626f6c3a20537472696e672c2065766d436f6e7472616374416464726573733a2045564d2e45564d416464726573732c20636f6e74726163745552493a20537472696e673f29207b0a202020202020202073656c662e65766d4e4654436f6e747261637441646472657373203d2065766d436f6e7472616374416464726573730a202020202020202073656c662e666c6f774e4654436f6e747261637441646472657373203d2073656c662e6163636f756e742e616464726573730a202020202020202073656c662e6e616d65203d206e616d650a202020202020202073656c662e73796d626f6c203d2073796d626f6c0a202020202020202073656c662e636f6e7472616374555249203d20636f6e74726163745552490a202020202020202073656c662e636f6c6c656374696f6e203c2d2063726561746520436f6c6c656374696f6e28290a0a2020202020202020466c6f7745564d427269646765436f6e6669672e6173736f63696174655479706528547970653c40" + "value": "2e4e46543e2829290a20202020202020202020202020202020202020207d290a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e20636f6c6c656374696f6e446174610a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020206c6574206d65646961203d204d6574616461746156696577732e4d65646961280a202020202020202020202020202020202020202066696c653a204d6574616461746156696577732e4854545046696c65280a20202020202020202020202020202020202020202020202075726c3a202268747470733a2f2f6173736574732e776562736974652d66696c65732e636f6d2f3566363239346330633761386364643634336231633832302f3566363239346330633761386364613535636231633933365f466c6f775f576f72646d61726b2e737667220a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206d65646961547970653a2022696d6167652f7376672b786d6c220a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e204d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c6179280a20202020202020202020202020202020202020206e616d653a202254686520466c6f77564d2042726964676564204e465420436f6c6c656374696f6e222c0a20202020202020202020202020202020202020206465736372697074696f6e3a20225468697320636f6c6c656374696f6e2077617320627269646765642066726f6d20466c6f772045564d2e222c0a202020202020202020202020202020202020202065787465726e616c55524c3a204d6574616461746156696577732e45787465726e616c55524c282268747470733a2f2f6272696467652e666c6f772e636f6d2f6e667422292c0a2020202020202020202020202020202020202020737175617265496d6167653a206d656469612c0a202020202020202020202020202020202020202062616e6e6572496d6167653a206d656469612c0a2020202020202020202020202020202020202020736f6369616c733a207b7d0a20202020202020202020202020202020290a2020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a2020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a20202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202020202020202020207572693a2073656c662e636f6e747261637455524920213d206e696c203f2043726f7373564d4e46542e5552492873656c662e636f6e74726163745552492129203a2043726f7373564d4e46542e555249282222290a20202020202020202020202020202020290a20202020202020207d0a202020202020202072657475726e206e696c0a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a2020202020202020496e7465726e616c204d6574686f64730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f206d696e74204e4654732066726f6d206272696467652d646566696e6564204e465420636f6e7472616374730a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e206d696e744e46542869643a2055496e743235362c20746f6b656e5552493a20537472696e67293a20404e4654207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d203d3d206e696c3a20224120746f6b656e20776974682074686520676976656e2045524337323120494420616c726561647920657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d20746f6b656e5552490a202020202020202072657475726e203c2d637265617465204e4654280a2020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202065766d49443a2069642c0a2020202020202020202020207572693a20746f6b656e5552492c0a2020202020202020202020206d657461646174613a207b0a20202020202020202020202020202020224272696467656420426c6f636b223a2067657443757272656e74426c6f636b28292e6865696768742c0a2020202020202020202020202020202022427269646765642054696d657374616d70223a2067657443757272656e74426c6f636b28292e74696d657374616d700a2020202020202020202020207d0a2020202020202020290a202020207d0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f207570646174652074686520555249206f662062726964676564204e4654732e205468697320617373756d65732074686174207468652045564d2d646566696e696e672070726f6a656374206d617920636f6e7461696e0a202020202f2f2f206c6f67696320286f6e636861696e206f72206f6666636861696e292077686963682075706461746573204e4654206d6574616461746120696e2074686520736f757263652045524337323120636f6e74726163742e204f6e206272696467696e672c20746865205552492063616e0a202020202f2f2f207468656e206265207570646174656420696e207468697320636f6e747261637420746f207265666c6563742074686520736f757263652045524337323120636f6e74726163742773206d657461646174612e0a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e207570646174655552492869643a2055496e743235362c206e65775552493a20537472696e6729207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d20213d206e696c3a20224e6f20746f6b656e20776974682074686520676976656e2045524337323120494420657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d206e65775552490a202020207d0a0a20202020696e6974286e616d653a20537472696e672c2073796d626f6c3a20537472696e672c2065766d436f6e7472616374416464726573733a2045564d2e45564d416464726573732c20636f6e74726163745552493a20537472696e673f29207b0a202020202020202073656c662e65766d4e4654436f6e747261637441646472657373203d2065766d436f6e7472616374416464726573730a202020202020202073656c662e666c6f774e4654436f6e747261637441646472657373203d2073656c662e6163636f756e742e616464726573730a202020202020202073656c662e6e616d65203d206e616d650a202020202020202073656c662e73796d626f6c203d2073796d626f6c0a202020202020202073656c662e636f6e7472616374555249203d20636f6e74726163745552490a202020202020202073656c662e746f6b656e55524973203d207b7d0a202020202020202073656c662e636f6c6c656374696f6e203c2d2063726561746520436f6c6c656374696f6e28290a0a2020202020202020466c6f7745564d427269646765436f6e6669672e6173736f63696174655479706528547970653c40" }, { "type": "String", "value": "2e4e46543e28292c20776974683a2073656c662e65766d4e4654436f6e747261637441646472657373290a2020202020202020466c6f7745564d4272696467654e4654457363726f772e696e697469616c697a65457363726f77280a202020202020202020202020666f72547970653a20547970653c40" diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index ade1e789..967d64fb 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -188,7 +188,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { value: 0.0 ) assert(transferResult.status == EVM.Status.successful, message: "Tranfer to bridge recipient failed") - + // And update the URI to reflect current metadata let updateURIResult: EVM.Result = FlowEVMBridgeUtils.call( signature: "updateTokenURI(uint256,string)", @@ -224,7 +224,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { /// Public entrypoint to bridge NFTs from EVM to Cadence /// - /// @param owner: The EVM address of the NFT owner. Current ownership and successful transfer (via + /// @param owner: The EVM address of the NFT owner. Current ownership and successful transfer (via /// `protectedTransferCall`) is validated before the bridge request is executed. /// @param calldata: Caller-provided approve() call, enabling contract COA to operate on NFT in EVM contract /// @param id: The NFT ID to bridged @@ -257,7 +257,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { // Get the EVMAddress of the ERC721 contract associated with the type let associatedAddress = FlowEVMBridgeConfig.getEVMAddressAssociated(with: type) ?? panic("No EVMAddress found for token type") - + // Ensure the caller is either the current owner or approved for the NFT let isAuthorized: Bool = FlowEVMBridgeUtils.isOwnerOrApproved( ofNFT: id, @@ -277,9 +277,18 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { evmContractAddress: associatedAddress ) assert(isEscrowed, message: "Transfer to bridge COA failed - cannot bridge NFT without bridge escrow") + // Get the token URI from the ERC721 contract + let uri = FlowEVMBridgeUtils.getTokenURI(evmContractAddress: associatedAddress, id: id) // If the NFT is currently locked, unlock and return if let cadenceID = FlowEVMBridgeNFTEscrow.getLockedCadenceID(type: type, evmID: id) { - return <-FlowEVMBridgeNFTEscrow.unlockNFT(type: type, id: cadenceID) + let nft <- FlowEVMBridgeNFTEscrow.unlockNFT(type: type, id: cadenceID) + + // If the NFT is bridge-defined, update the URI from the source ERC721 contract + if self.account.address == FlowEVMBridgeUtils.getContractAddress(fromType: type) { + nft.updateTokenURI(uri) + } + + return <-nft } // Otherwise, we expect the NFT to be minted in Cadence let contractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: type)! @@ -287,7 +296,6 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { let contractName = FlowEVMBridgeUtils.getContractName(fromType: type)! let nftContract = getAccount(contractAddress).contracts.borrow<&{IEVMBridgeNFTMinter}>(name: contractName)! - let uri = FlowEVMBridgeUtils.getTokenURI(evmContractAddress: associatedAddress, id: id) let nft <- nftContract.mintNFT(id: id, tokenURI: uri) return <-nft } diff --git a/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc b/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc index 45cb7aeb..17e17e28 100644 --- a/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc +++ b/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc @@ -42,6 +42,10 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi access(all) var contractURI: String? /// Retain a Collection to reference when resolving Collection Metadata access(self) let collection: @Collection + /// Mapping of token URIs indexed on their ERC721 ID. This would not normally be retained within a Cadence NFT + /// contract, but since NFT metadata may be updated in EVM, it's retained here so that the bridge can update + /// it against the source ERC721 contract which is treated as the NFT's source of truth. + access(all) let tokenURIs: {UInt256: String} /// The NFT resource representing the bridged ERC721 token /// @@ -54,8 +58,6 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi access(all) let name: String /// The symbol of the NFT as defined in the ERC721 contract access(all) let symbol: String - /// The URI of the NFT as defined in the ERC721 contract - access(all) let uri: String /// Additional onchain metadata access(all) let metadata: {String: AnyStruct} @@ -63,14 +65,12 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi name: String, symbol: String, evmID: UInt256, - uri: String, metadata: {String: AnyStruct} ) { self.name = name self.symbol = symbol self.id = self.uuid self.evmID = evmID - self.uri = uri self.metadata = metadata } @@ -127,7 +127,15 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi /// Similar to ERC721.tokenURI method, returns the URI of the NFT with self.evmID at time of bridging access(all) view fun tokenURI(): String { - return self.uri + return {{CONTRACT_NAME}}.tokenURIs[self.evmID] ?? "" + } + + /* --- Bridge only method --- */ + // + /// Allows the bridge to update the URI against the source ERC721 contract on bridging back to Cadence + access(account) + fun updateURI(_ new: String) { + {{CONTRACT_NAME}}.updateTokenURI(id: self.evmID, newURI: new) } } @@ -330,9 +338,14 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi Internal Methods ***********************/ - /// Allows the bridge to + /// Allows the bridge to mint NFTs from bridge-defined NFT contracts + /// access(account) fun mintNFT(id: UInt256, tokenURI: String): @NFT { + pre { + self.tokenURIs[id] == nil: "A token with the given ERC721 ID already exists" + } + self.tokenURIs[id] = tokenURI return <-create NFT( name: self.name, symbol: self.symbol, @@ -345,12 +358,25 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi ) } + /// Allows the bridge to update the URI of bridged NFTs. This assumes that the EVM-defining project may contain + /// logic (onchain or offchain) which updates NFT metadata in the source ERC721 contract. On bridging, the URI can + /// then be updated in this contract to reflect the source ERC721 contract's metadata. + /// + access(account) + fun updateURI(id: UInt256, newURI: String) { + pre { + self.tokenURIs[id] != nil: "No token with the given ERC721 ID exists" + } + self.tokenURIs[id] = newURI + } + init(name: String, symbol: String, evmContractAddress: EVM.EVMAddress, contractURI: String?) { self.evmNFTContractAddress = evmContractAddress self.flowNFTContractAddress = self.account.address self.name = name self.symbol = symbol self.contractURI = contractURI + self.tokenURIs = {} self.collection <- create Collection() FlowEVMBridgeConfig.associateType(Type<@{{CONTRACT_NAME}}.NFT>(), with: self.evmNFTContractAddress) From 229b2be11bf9e90939e9ccdf90f67cf7d6febec8 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:44:56 -0500 Subject: [PATCH 15/39] update serialize_tests.cdc --- cadence/tests/Serialize_tests.cdc | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/cadence/tests/Serialize_tests.cdc b/cadence/tests/Serialize_tests.cdc index cdfd30fb..91daa122 100644 --- a/cadence/tests/Serialize_tests.cdc +++ b/cadence/tests/Serialize_tests.cdc @@ -13,17 +13,6 @@ let admin = Test.getAccount(0x0000000000000007) access(all) let alice = Test.createAccount() -// access(all) -// let testSerializableStructOutput = "{\"trait_type\": \"Name\", \"value\": \"TestSerializableStruct\"}" - -// access(all) -// struct TestSerializableStruct : SerializationInterfaces.SerializableStruct { -// access(all) -// fun serialize(): String { -// return testSerializableStructOutput -// } -// } - access(all) fun setup() { var err = Test.deployContract( From 03fa0461ee273d1f5dd9485119ef5f0cfc943cd7 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:18:07 -0500 Subject: [PATCH 16/39] fix conformance errors & update setup commands --- .../args/bridged-nft-code-chunks-args.json | 9 ++-- cadence/contracts/bridge/FlowEVMBridge.cdc | 31 ++++++------ .../contracts/bridge/IEVMBridgeNFTMinter.cdc | 7 +++ .../emulator/EVMBridgedNFTTemplate.cdc | 21 +++------ flow.json | 12 ++--- local/setup_emulator.1.sh | 20 ++++---- local/setup_emulator.2.sh | 47 ++++++++++--------- local/setup_emulator.3.sh | 2 +- 8 files changed, 77 insertions(+), 72 deletions(-) diff --git a/cadence/args/bridged-nft-code-chunks-args.json b/cadence/args/bridged-nft-code-chunks-args.json index f451dd38..b506de26 100644 --- a/cadence/args/bridged-nft-code-chunks-args.json +++ b/cadence/args/bridged-nft-code-chunks-args.json @@ -10,7 +10,7 @@ "value": "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078663864366530353836623061323063370a696d706f7274204d6574616461746156696577732066726f6d203078663864366530353836623061323063370a696d706f727420566965775265736f6c7665722066726f6d203078663864366530353836623061323063370a696d706f72742046756e6769626c65546f6b656e2066726f6d203078656538323835366266323065326161360a696d706f727420466c6f77546f6b656e2066726f6d203078306165353363623665336634326137390a0a696d706f72742045564d2066726f6d203078663864366530353836623061323063370a0a696d706f7274204943726f7373564d2066726f6d203078663864366530353836623061323063370a696d706f7274204945564d4272696467654e46544d696e7465722066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467654e4654457363726f772066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d427269646765436f6e6669672066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467655574696c732066726f6d203078663864366530353836623061323063370a696d706f727420466c6f7745564d4272696467652066726f6d203078663864366530353836623061323063370a696d706f72742043726f7373564d4e46542066726f6d203078663864366530353836623061323063370a0a2f2f2f205468697320636f6e747261637420697320612074656d706c617465207573656420627920466c6f7745564d42726964676520746f20646566696e652045564d2d6e6174697665204e46547320627269646765642066726f6d20466c6f772045564d20746f20466c6f772e0a2f2f2f2055706f6e206465706c6f796d656e74206f66207468697320636f6e74726163742c2074686520636f6e7472616374206e616d65206973206465726976656420617320612066756e6374696f6e206f6620746865206173736574207479706520286865726520616e2045524337323120616b610a2f2f2f20616e204e46542920616e642074686520636f6e747261637427732045564d20616464726573732e20546865206465726976656420636f6e7472616374206e616d65206973207468656e206a6f696e65642077697468207468697320636f6e7472616374277320636f64652c0a2f2f2f207072657061726564206173206368756e6b7320696e20466c6f7745564d42726964676554656d706c61746573206265666f7265206265696e67206465706c6f79656420746f2074686520466c6f772045564d20427269646765206163636f756e742e0a2f2f2f0a2f2f2f204f6e206272696467696e672c2074686520455243373231206973207472616e7366657272656420746f2074686520627269646765277320436164656e63654f776e65644163636f756e742045564d206164647265737320616e642061206e6577204e4654206973206d696e7465642066726f6d0a2f2f2f207468697320636f6e747261637420746f20746865206272696467696e672063616c6c65722e204f6e2072657475726e20746f20466c6f772045564d2c2074686520726576657273652070726f6365737320697320666f6c6c6f776564202d2074686520746f6b656e206973206275726e65640a2f2f2f20696e207468697320636f6e747261637420616e642074686520455243373231206973207472616e7366657272656420746f2074686520646566696e656420726563697069656e742e20496e2074686973207761792c2074686520436164656e636520746f6b656e206163747320617320610a2f2f2f20726570726573656e746174696f6e206f6620626f7468207468652045564d204e465420616e642074687573206f776e6572736869702072696768747320746f2069742075706f6e206272696467696e67206261636b20746f20466c6f772045564d2e0a2f2f2f0a2f2f2f20546f20627269646765206265747765656e20564d732c20612063616c6c65722063616e20656974686572207573652074686520636f6e7472616374206d6574686f647320646566696e65642062656c6f772c206f72207573652074686520466c6f7745564d42726964676527730a2f2f2f206272696467696e67206d6574686f64732077686963682077696c6c2070726f6772616d61746963616c6c7920726f757465206272696467696e672063616c6c7320746f207468697320636f6e74726163742e0a2f2f2f0a2f2f20544f444f3a20496d706c656d656e74204e465420636f6e747261637420696e74657266616365206f6e636520763220617661696c61626c65206c6f63616c6c790a61636365737328616c6c2920636f6e747261637420" }, { "type": "String", - "value": "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e5552492873656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20" + "value": "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20" }, { "type": "String", "value": "2e7265736f6c7665436f6e747261637456696577280a2020202020202020202020202020202020202020202020207265736f75726365547970653a2073656c662e6765745479706528292c0a20202020202020202020202020202020202020202020202076696577547970653a20547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020202020202072657475726e20" @@ -25,10 +25,7 @@ "value": "2e67657445564d436f6e74726163744164647265737328290a20202020202020207d0a0a20202020202020202f2f2f2053696d696c617220746f204552433732312e746f6b656e555249206d6574686f642c2072657475726e732074686520555249206f6620746865204e465420776974682073656c662e65766d49442061742074696d65206f66206272696467696e670a202020202020202061636365737328616c6c2920766965772066756e20746f6b656e55524928293a20537472696e67207b0a20202020202020202020202072657475726e20" }, { "type": "String", - "value": "2e746f6b656e555249735b73656c662e65766d49445d203f3f2022220a20202020202020207d0a0a20202020202020202f2a202d2d2d20427269646765206f6e6c79206d6574686f64202d2d2d202a2f0a20202020202020202f2f0a20202020202020202f2f2f20416c6c6f7773207468652062726964676520746f20757064617465207468652055524920616761696e73742074686520736f757263652045524337323120636f6e7472616374206f6e206272696467696e67206261636b20746f20436164656e63650a2020202020202020616363657373286163636f756e74290a202020202020202066756e20757064617465555249285f206e65773a20537472696e6729207b0a202020202020202020202020" - }, { - "type": "String", - "value": "2e757064617465546f6b656e5552492869643a2073656c662e65766d49442c206e65775552493a206e6577290a20202020202020207d0a202020207d0a0a202020202f2f2f2054686973207265736f7572636520686f6c6473206173736f636961746564204e4654732c20616e642073657276657320717565726965732061626f75742073746f726564204e4654730a2020202061636365737328616c6c29207265736f7572636520436f6c6c656374696f6e3a204e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e2c2043726f7373564d4e46542e45564d4e4654436f6c6c656374696f6e207b0a20202020202020202f2f2f2064696374696f6e617279206f66204e465420636f6e666f726d696e6720746f6b656e7320696e6465786564206f6e2074686569722049440a202020202020202061636365737328636f6e74726163742920766172206f776e65644e4654733a20407b55496e7436343a20" + "value": "2e746f6b656e555249735b73656c662e65766d49445d203f3f2022220a20202020202020207d0a202020207d0a0a202020202f2f2f2054686973207265736f7572636520686f6c6473206173736f636961746564204e4654732c20616e642073657276657320717565726965732061626f75742073746f726564204e4654730a2020202061636365737328616c6c29207265736f7572636520436f6c6c656374696f6e3a204e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e2c2043726f7373564d4e46542e45564d4e4654436f6c6c656374696f6e207b0a20202020202020202f2f2f2064696374696f6e617279206f66204e465420636f6e666f726d696e6720746f6b656e7320696e6465786564206f6e2074686569722049440a202020202020202061636365737328636f6e74726163742920766172206f776e65644e4654733a20407b55496e7436343a20" }, { "type": "String", "value": "2e4e46547d0a20202020202020202f2f2f204d617070696e67206f662045564d2049447320746f20466c6f77204e4654204944730a202020202020202061636365737328636f6e747261637429206c65742065766d4944546f466c6f7749443a207b55496e743235363a2055496e7436347d0a0a202020202020202061636365737328616c6c29207661722073746f72616765506174683a2053746f72616765506174680a202020202020202061636365737328616c6c2920766172207075626c6963506174683a205075626c6963506174680a0a2020202020202020696e6974202829207b0a20202020202020202020202073656c662e6f776e65644e465473203c2d207b7d0a20202020202020202020202073656c662e65766d4944546f466c6f774944203d207b7d0a2020202020202020202020206c657420636f6c6c656374696f6e44617461203d20" @@ -73,7 +70,7 @@ "value": "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a20547970653c40" }, { "type": "String", - "value": "2e4e46543e2829290a20202020202020202020202020202020202020207d290a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e20636f6c6c656374696f6e446174610a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020206c6574206d65646961203d204d6574616461746156696577732e4d65646961280a202020202020202020202020202020202020202066696c653a204d6574616461746156696577732e4854545046696c65280a20202020202020202020202020202020202020202020202075726c3a202268747470733a2f2f6173736574732e776562736974652d66696c65732e636f6d2f3566363239346330633761386364643634336231633832302f3566363239346330633761386364613535636231633933365f466c6f775f576f72646d61726b2e737667220a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206d65646961547970653a2022696d6167652f7376672b786d6c220a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e204d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c6179280a20202020202020202020202020202020202020206e616d653a202254686520466c6f77564d2042726964676564204e465420436f6c6c656374696f6e222c0a20202020202020202020202020202020202020206465736372697074696f6e3a20225468697320636f6c6c656374696f6e2077617320627269646765642066726f6d20466c6f772045564d2e222c0a202020202020202020202020202020202020202065787465726e616c55524c3a204d6574616461746156696577732e45787465726e616c55524c282268747470733a2f2f6272696467652e666c6f772e636f6d2f6e667422292c0a2020202020202020202020202020202020202020737175617265496d6167653a206d656469612c0a202020202020202020202020202020202020202062616e6e6572496d6167653a206d656469612c0a2020202020202020202020202020202020202020736f6369616c733a207b7d0a20202020202020202020202020202020290a2020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a2020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a20202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202020202020202020207572693a2073656c662e636f6e747261637455524920213d206e696c203f2043726f7373564d4e46542e5552492873656c662e636f6e74726163745552492129203a2043726f7373564d4e46542e555249282222290a20202020202020202020202020202020290a20202020202020207d0a202020202020202072657475726e206e696c0a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a2020202020202020496e7465726e616c204d6574686f64730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f206d696e74204e4654732066726f6d206272696467652d646566696e6564204e465420636f6e7472616374730a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e206d696e744e46542869643a2055496e743235362c20746f6b656e5552493a20537472696e67293a20404e4654207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d203d3d206e696c3a20224120746f6b656e20776974682074686520676976656e2045524337323120494420616c726561647920657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d20746f6b656e5552490a202020202020202072657475726e203c2d637265617465204e4654280a2020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202065766d49443a2069642c0a2020202020202020202020207572693a20746f6b656e5552492c0a2020202020202020202020206d657461646174613a207b0a20202020202020202020202020202020224272696467656420426c6f636b223a2067657443757272656e74426c6f636b28292e6865696768742c0a2020202020202020202020202020202022427269646765642054696d657374616d70223a2067657443757272656e74426c6f636b28292e74696d657374616d700a2020202020202020202020207d0a2020202020202020290a202020207d0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f207570646174652074686520555249206f662062726964676564204e4654732e205468697320617373756d65732074686174207468652045564d2d646566696e696e672070726f6a656374206d617920636f6e7461696e0a202020202f2f2f206c6f67696320286f6e636861696e206f72206f6666636861696e292077686963682075706461746573204e4654206d6574616461746120696e2074686520736f757263652045524337323120636f6e74726163742e204f6e206272696467696e672c20746865205552492063616e0a202020202f2f2f207468656e206265207570646174656420696e207468697320636f6e747261637420746f207265666c6563742074686520736f757263652045524337323120636f6e74726163742773206d657461646174612e0a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e207570646174655552492869643a2055496e743235362c206e65775552493a20537472696e6729207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d20213d206e696c3a20224e6f20746f6b656e20776974682074686520676976656e2045524337323120494420657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d206e65775552490a202020207d0a0a20202020696e6974286e616d653a20537472696e672c2073796d626f6c3a20537472696e672c2065766d436f6e7472616374416464726573733a2045564d2e45564d416464726573732c20636f6e74726163745552493a20537472696e673f29207b0a202020202020202073656c662e65766d4e4654436f6e747261637441646472657373203d2065766d436f6e7472616374416464726573730a202020202020202073656c662e666c6f774e4654436f6e747261637441646472657373203d2073656c662e6163636f756e742e616464726573730a202020202020202073656c662e6e616d65203d206e616d650a202020202020202073656c662e73796d626f6c203d2073796d626f6c0a202020202020202073656c662e636f6e7472616374555249203d20636f6e74726163745552490a202020202020202073656c662e746f6b656e55524973203d207b7d0a202020202020202073656c662e636f6c6c656374696f6e203c2d2063726561746520436f6c6c656374696f6e28290a0a2020202020202020466c6f7745564d427269646765436f6e6669672e6173736f63696174655479706528547970653c40" + "value": "2e4e46543e2829290a20202020202020202020202020202020202020207d290a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e20636f6c6c656374696f6e446174610a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020206c6574206d65646961203d204d6574616461746156696577732e4d65646961280a202020202020202020202020202020202020202066696c653a204d6574616461746156696577732e4854545046696c65280a20202020202020202020202020202020202020202020202075726c3a202268747470733a2f2f6173736574732e776562736974652d66696c65732e636f6d2f3566363239346330633761386364643634336231633832302f3566363239346330633761386364613535636231633933365f466c6f775f576f72646d61726b2e737667220a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206d65646961547970653a2022696d6167652f7376672b786d6c220a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e204d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c6179280a20202020202020202020202020202020202020206e616d653a202254686520466c6f77564d2042726964676564204e465420436f6c6c656374696f6e222c0a20202020202020202020202020202020202020206465736372697074696f6e3a20225468697320636f6c6c656374696f6e2077617320627269646765642066726f6d20466c6f772045564d2e222c0a202020202020202020202020202020202020202065787465726e616c55524c3a204d6574616461746156696577732e45787465726e616c55524c282268747470733a2f2f6272696467652e666c6f772e636f6d2f6e667422292c0a2020202020202020202020202020202020202020737175617265496d6167653a206d656469612c0a202020202020202020202020202020202020202062616e6e6572496d6167653a206d656469612c0a2020202020202020202020202020202020202020736f6369616c733a207b7d0a20202020202020202020202020202020290a2020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a2020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a20202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202020202020202020207572693a2073656c662e636f6e747261637455524920213d206e696c203f2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e636f6e74726163745552492129203a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a202222290a20202020202020202020202020202020290a20202020202020207d0a202020202020202072657475726e206e696c0a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a2020202020202020496e7465726e616c204d6574686f64730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f206d696e74204e4654732066726f6d206272696467652d646566696e6564204e465420636f6e7472616374730a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e206d696e744e46542869643a2055496e743235362c20746f6b656e5552493a20537472696e67293a20404e4654207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d203d3d206e696c3a20224120746f6b656e20776974682074686520676976656e2045524337323120494420616c726561647920657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d20746f6b656e5552490a202020202020202072657475726e203c2d637265617465204e4654280a2020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202065766d49443a2069642c0a2020202020202020202020206d657461646174613a207b0a20202020202020202020202020202020224272696467656420426c6f636b223a2067657443757272656e74426c6f636b28292e6865696768742c0a2020202020202020202020202020202022427269646765642054696d657374616d70223a2067657443757272656e74426c6f636b28292e74696d657374616d700a2020202020202020202020207d0a2020202020202020290a202020207d0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f207570646174652074686520555249206f662062726964676564204e4654732e205468697320617373756d65732074686174207468652045564d2d646566696e696e672070726f6a656374206d617920636f6e7461696e0a202020202f2f2f206c6f67696320286f6e636861696e206f72206f6666636861696e292077686963682075706461746573204e4654206d6574616461746120696e2074686520736f757263652045524337323120636f6e74726163742e204f6e206272696467696e672c20746865205552492063616e0a202020202f2f2f207468656e206265207570646174656420696e207468697320636f6e747261637420746f207265666c6563742074686520736f757263652045524337323120636f6e74726163742773206d657461646174612e0a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e20757064617465546f6b656e5552492865766d49443a2055496e743235362c206e65775552493a20537472696e6729207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b65766d49445d20213d206e696c3a20224e6f20746f6b656e20776974682074686520676976656e2045524337323120494420657869737473220a20202020202020207d0a202020202020202069662073656c662e746f6b656e555249735b65766d49445d20213d206e6577555249207b0a20202020202020202020202073656c662e746f6b656e555249735b65766d49445d203d206e65775552490a20202020202020207d0a202020207d0a0a20202020696e6974286e616d653a20537472696e672c2073796d626f6c3a20537472696e672c2065766d436f6e7472616374416464726573733a2045564d2e45564d416464726573732c20636f6e74726163745552493a20537472696e673f29207b0a202020202020202073656c662e65766d4e4654436f6e747261637441646472657373203d2065766d436f6e7472616374416464726573730a202020202020202073656c662e666c6f774e4654436f6e747261637441646472657373203d2073656c662e6163636f756e742e616464726573730a202020202020202073656c662e6e616d65203d206e616d650a202020202020202073656c662e73796d626f6c203d2073796d626f6c0a202020202020202073656c662e636f6e7472616374555249203d20636f6e74726163745552490a202020202020202073656c662e746f6b656e55524973203d207b7d0a202020202020202073656c662e636f6c6c656374696f6e203c2d2063726561746520436f6c6c656374696f6e28290a0a2020202020202020466c6f7745564d427269646765436f6e6669672e6173736f63696174655479706528547970653c40" }, { "type": "String", "value": "2e4e46543e28292c20776974683a2073656c662e65766d4e4654436f6e747261637441646472657373290a2020202020202020466c6f7745564d4272696467654e4654457363726f772e696e697469616c697a65457363726f77280a202020202020202020202020666f72547970653a20547970653c40" diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index 967d64fb..f63be6f5 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -137,6 +137,16 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { let tokenID = token.id let evmID = CrossVMNFT.getEVMID(from: &token as &{NonFungibleToken.NFT}) ?? UInt256(token.id) + // Grab the URI from the NFT if available + var uri: String = "" + // Default to project-specified URI + if let metadata = token.resolveView(Type()) as! CrossVMNFT.EVMBridgedMetadata? { + uri = metadata.uri.uri() + } else { + // Otherwise, serialize the NFT using OpenSea Metadata strategy + uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT}) + } + // Lock the NFT & calculate the storage used by the NFT let storageUsed = FlowEVMBridgeNFTEscrow.lockNFT(<-token) // Calculate the bridge fee on current rates @@ -155,15 +165,6 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { let isFactoryDeployed = FlowEVMBridgeUtils.isEVMContractBridgeOwned(evmContractAddress: associatedAddress) // Controlled by the bridge - mint or transfer based on existence if isFactoryDeployed { - // Grab the URI from the NFT if available - var uri: String = "" - // Default to project-specified URI - if let metadata = token.resolveView(Type()) as! CrossVMNFT.EVMBridgedMetadata? { - uri = metadata.uri.uri() - } else { - // Otherwise, serialize the NFT using OpenSea Metadata strategy - uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT}) - } // Check if the ERC721 exists let existsResponse = EVM.decodeABI( @@ -277,6 +278,11 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { evmContractAddress: associatedAddress ) assert(isEscrowed, message: "Transfer to bridge COA failed - cannot bridge NFT without bridge escrow") + + // Derive the defining Cadence contract name & address & attempt to borrow it as IEVMBridgeNFTMinter + let contractName = FlowEVMBridgeUtils.getContractName(fromType: type)! + let contractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: type)! + let nftContract = getAccount(contractAddress).contracts.borrow<&{IEVMBridgeNFTMinter}>(name: contractName) // Get the token URI from the ERC721 contract let uri = FlowEVMBridgeUtils.getTokenURI(evmContractAddress: associatedAddress, id: id) // If the NFT is currently locked, unlock and return @@ -285,18 +291,15 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { // If the NFT is bridge-defined, update the URI from the source ERC721 contract if self.account.address == FlowEVMBridgeUtils.getContractAddress(fromType: type) { - nft.updateTokenURI(uri) + nftContract!.updateTokenURI(evmID: id, newURI: uri) } return <-nft } // Otherwise, we expect the NFT to be minted in Cadence - let contractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: type)! assert(self.account.address == contractAddress, message: "Unexpected error bridging NFT from EVM") - let contractName = FlowEVMBridgeUtils.getContractName(fromType: type)! - let nftContract = getAccount(contractAddress).contracts.borrow<&{IEVMBridgeNFTMinter}>(name: contractName)! - let nft <- nftContract.mintNFT(id: id, tokenURI: uri) + let nft <- nftContract!.mintNFT(id: id, tokenURI: uri) return <-nft } diff --git a/cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc b/cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc index 8c6b09c1..ef74aa74 100644 --- a/cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc +++ b/cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc @@ -9,4 +9,11 @@ contract interface IEVMBridgeNFTMinter { /// access(account) fun mintNFT(id: UInt256, tokenURI: String): @{NonFungibleToken.NFT} + + /// Allows the bridge to update the URI of bridged NFTs. This assumes that the EVM-defining project may contain + /// logic (onchain or offchain) which updates NFT metadata in the source ERC721 contract. On bridging, the URI can + /// then be updated in this contract to reflect the source ERC721 contract's metadata. + /// + access(account) + fun updateTokenURI(evmID: UInt256, newURI: String) } diff --git a/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc b/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc index 17e17e28..6b2bbc2c 100644 --- a/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc +++ b/cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc @@ -93,7 +93,7 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi return CrossVMNFT.EVMBridgedMetadata( name: self.name, symbol: self.symbol, - uri: CrossVMNFT.URI(self.tokenURI()) + uri: CrossVMNFT.URI(baseURI: nil, value: self.tokenURI()) ) case Type(): return MetadataViews.Serial( @@ -129,14 +129,6 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi access(all) view fun tokenURI(): String { return {{CONTRACT_NAME}}.tokenURIs[self.evmID] ?? "" } - - /* --- Bridge only method --- */ - // - /// Allows the bridge to update the URI against the source ERC721 contract on bridging back to Cadence - access(account) - fun updateURI(_ new: String) { - {{CONTRACT_NAME}}.updateTokenURI(id: self.evmID, newURI: new) - } } /// This resource holds associated NFTs, and serves queries about stored NFTs @@ -328,7 +320,7 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi return CrossVMNFT.EVMBridgedMetadata( name: self.name, symbol: self.symbol, - uri: self.contractURI != nil ? CrossVMNFT.URI(self.contractURI!) : CrossVMNFT.URI("") + uri: self.contractURI != nil ? CrossVMNFT.URI(baseURI: nil, value: self.contractURI!) : CrossVMNFT.URI(baseURI: nil, value: "") ) } return nil @@ -350,7 +342,6 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi name: self.name, symbol: self.symbol, evmID: id, - uri: tokenURI, metadata: { "Bridged Block": getCurrentBlock().height, "Bridged Timestamp": getCurrentBlock().timestamp @@ -363,11 +354,13 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi /// then be updated in this contract to reflect the source ERC721 contract's metadata. /// access(account) - fun updateURI(id: UInt256, newURI: String) { + fun updateTokenURI(evmID: UInt256, newURI: String) { pre { - self.tokenURIs[id] != nil: "No token with the given ERC721 ID exists" + self.tokenURIs[evmID] != nil: "No token with the given ERC721 ID exists" + } + if self.tokenURIs[evmID] != newURI { + self.tokenURIs[evmID] = newURI } - self.tokenURIs[id] = newURI } init(name: String, symbol: String, evmContractAddress: EVM.EVMAddress, contractURI: String?) { diff --git a/flow.json b/flow.json index 9b42a063..11422490 100644 --- a/flow.json +++ b/flow.json @@ -149,22 +149,22 @@ "emulator": "f8d6e0586b0a20c7" } }, - "Serialize": { - "source": "./cadence/contracts/utils/Serialize.cdc", + "SerializationInterfaces": { + "source": "./cadence/contracts/utils/SerializationInterfaces.cdc", "aliases": { "emulator": "f8d6e0586b0a20c7", "testing": "0000000000000007" } }, - "SerializeNFT": { - "source": "./cadence/contracts/utils/SerializeNFT.cdc", + "Serialize": { + "source": "./cadence/contracts/utils/Serialize.cdc", "aliases": { "emulator": "f8d6e0586b0a20c7", "testing": "0000000000000007" } }, - "SerializationInterfaces": { - "source": "./cadence/contracts/utils/SerializationInterfaces.cdc", + "SerializeNFT": { + "source": "./cadence/contracts/utils/SerializeNFT.cdc", "aliases": { "emulator": "f8d6e0586b0a20c7", "testing": "0000000000000007" diff --git a/local/setup_emulator.1.sh b/local/setup_emulator.1.sh index 5e19e876..20641e18 100644 --- a/local/setup_emulator.1.sh +++ b/local/setup_emulator.1.sh @@ -1,21 +1,21 @@ #!/bin/bash -flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 100.0 +flow transactions send ./cadence/transactions/evm/create_account.cdc 100.0 -flow-c1 accounts add-contract ./cadence/contracts/utils/ArrayUtils.cdc -flow-c1 accounts add-contract ./cadence/contracts/utils/StringUtils.cdc -flow-c1 accounts add-contract ./cadence/contracts/utils/ScopedFTProviders.cdc +flow accounts add-contract ./cadence/contracts/utils/ArrayUtils.cdc +flow accounts add-contract ./cadence/contracts/utils/StringUtils.cdc +flow accounts add-contract ./cadence/contracts/utils/ScopedFTProviders.cdc -flow-c1 accounts update-contract ./cadence/contracts/standards/EVM.cdc +flow accounts update-contract ./cadence/contracts/standards/EVM.cdc # Create COA in emulator-account # Deploy the Factory contract - NOTE THE `deployedContractAddress` IN THE EMITTED EVENT -flow-c1 transactions send ./cadence/transactions/evm/deploy.cdc \ +flow transactions send ./cadence/transactions/evm/deploy.cdc \ --args-json "$(cat ./cadence/args/deploy-factory-args.json)" # Deploy initial bridge contracts -flow-c1 accounts add-contract ./cadence/contracts/bridge/BridgePermissions.cdc -flow-c1 accounts add-contract ./cadence/contracts/bridge/ICrossVM.cdc -flow-c1 accounts add-contract ./cadence/contracts/bridge/CrossVMNFT.cdc -flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc \ No newline at end of file +flow accounts add-contract ./cadence/contracts/bridge/BridgePermissions.cdc +flow accounts add-contract ./cadence/contracts/bridge/ICrossVM.cdc +flow accounts add-contract ./cadence/contracts/bridge/CrossVMNFT.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc \ No newline at end of file diff --git a/local/setup_emulator.2.sh b/local/setup_emulator.2.sh index ee98fcf7..17b19c66 100644 --- a/local/setup_emulator.2.sh +++ b/local/setup_emulator.2.sh @@ -1,55 +1,60 @@ # Provided address is the address of the Factory contract deployed in the previous txn -flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \ +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \ -flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc -flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc # Add the templated contract code chunks for FlowEVMBridgedNFTTemplate.cdc contents -flow-c1 transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \ +flow transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \ --args-json "$(cat ./cadence/args/bridged-nft-code-chunks-args.json)" --gas-limit 1600 -flow-c1 accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc +flow accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc + +# Deploy Serialization Utils +flow accounts add-contract ./cadence/contracts/utils/SerializationInterfaces.cdc +flow accounts add-contract ./cadence/contracts/utils/Serialize.cdc +flow accounts add-contract ./cadence/contracts/utils/SerializeNFT.cdc # Deploy main bridge interface & contract -flow-c1 accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc -flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc +flow accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc # Deploy the bridge router directing calls from COAs to the dedicated bridge -flow-c1 accounts add-contract ./cadence/contracts/bridge/EVMBridgeRouter.cdc 0xf8d6e0586b0a20c7 FlowEVMBridge +flow accounts add-contract ./cadence/contracts/bridge/EVMBridgeRouter.cdc 0xf8d6e0586b0a20c7 FlowEVMBridge # Create `example-nft` account 179b6b1cb6755e31 with private key 96dfbadf086daa187100a24b1fd2b709b702954bbd030a394148e11bcbb799ef -flow-c1 accounts create --key "351e1310301a7374430f6077d7b1b679c9574f8e045234eac09568ceb15c4f5d937104b4c3180df1e416da20c9d58aac576ffc328a342198a5eae4a29a13c47a" +flow accounts create --key "351e1310301a7374430f6077d7b1b679c9574f8e045234eac09568ceb15c4f5d937104b4c3180df1e416da20c9d58aac576ffc328a342198a5eae4a29a13c47a" # Create `user` account 0xf3fcd2c1a78f5eee with private key bce84aae316aec618888e5bdd24a3c8b8af46896c1ebe457e2f202a4a9c43075 -flow-c1 accounts create --key "c695fa608bd40821552fae13bb710c917309690ed69c22866abad19d276c99296379358321d0123d7074c817dd646ae8f651734526179eaed9f33eba16601ff6" +flow accounts create --key "c695fa608bd40821552fae13bb710c917309690ed69c22866abad19d276c99296379358321d0123d7074c817dd646ae8f651734526179eaed9f33eba16601ff6" # Create `erc721` account 0xe03daebed8ca0615 with private key bf602a4cdffb5610a008622f6601ba7059f8a6f533d7489457deb3d45875acb0 -flow-c1 accounts create --key "9103fd9106a83a2ede667e2486848e13e5854ea512af9bbec9ad2aec155bd5b5c146b53a6c3fd619c591ae0cd730acb875e5b6e074047cf31d620b53c55a4fb4" +flow accounts create --key "9103fd9106a83a2ede667e2486848e13e5854ea512af9bbec9ad2aec155bd5b5c146b53a6c3fd619c591ae0cd730acb875e5b6e074047cf31d620b53c55a4fb4" # Give the user some FLOW -flow-c1 transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xf3fcd2c1a78f5eee 100.0 +flow transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xf3fcd2c1a78f5eee 100.0 # Give the erc721 some FLOW -flow-c1 transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xe03daebed8ca0615 100.0 +flow transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xe03daebed8ca0615 100.0 # Create a COA for the user -flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer user +flow transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer user # Create a COA for the erc721 -flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer erc721 +flow transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer erc721 # user transfers Flow to the COA -flow-c1 transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer user +flow transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer user # erc721 transfers Flow to the COA -flow-c1 transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer erc721 +flow transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer erc721 # Setup User with Example NFT collection - Will break flow.json config due to bug in CLI - break here and update flow.json manually -flow-c1 accounts add-contract ./cadence/contracts/example-assets/ExampleNFT.cdc --signer example-nft +flow accounts add-contract ./cadence/contracts/example-assets/ExampleNFT.cdc --signer example-nft -flow-c1 transactions send ./cadence/transactions/example-assets/setup_collection.cdc --signer user -flow-c1 transactions send ./cadence/transactions/example-assets/mint_nft.cdc f3fcd2c1a78f5eee example description thumbnail '[]' '[]' '[]' --signer example-nft +flow transactions send ./cadence/transactions/example-assets/setup_collection.cdc --signer user +flow transactions send ./cadence/transactions/example-assets/mint_nft.cdc f3fcd2c1a78f5eee example description thumbnail '[]' '[]' '[]' --signer example-nft # Deploy ExampleERC721 contract with erc721's COA as owner - NOTE THE `deployedContractAddress` EMITTED IN THE RESULTING EVENT -flow-c1 transactions send ./cadence/transactions/evm/deploy.cdc \ +flow transactions send ./cadence/transactions/evm/deploy.cdc \ --args-json "$(cat ./cadence/args/deploy-erc721-args.json)" --signer erc721 \ No newline at end of file diff --git a/local/setup_emulator.3.sh b/local/setup_emulator.3.sh index 6485be51..0b7f6054 100644 --- a/local/setup_emulator.3.sh +++ b/local/setup_emulator.3.sh @@ -1,4 +1,4 @@ # Mint an ERC721 with ID 42 to the user's COA -flow-c1 transactions send ./cadence/transactions/example-assets/safe_mint_erc721.cdc \ +flow transactions send ./cadence/transactions/example-assets/safe_mint_erc721.cdc \ 42 "URI" 200000 \ --signer erc721 From 6f6af18add876fcaeef03db9806d955232f4fe9d Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:59:53 -0500 Subject: [PATCH 17/39] update serialization tests --- cadence/tests/serialize_nft_tests.cdc | 39 ++++++++++++------- ...erialize_tests.cdc => serialize_tests.cdc} | 4 -- 2 files changed, 25 insertions(+), 18 deletions(-) rename cadence/tests/{Serialize_tests.cdc => serialize_tests.cdc} (99%) diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index a9291169..33e392d7 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -1,17 +1,13 @@ import Test import BlockchainHelpers -import "NonFungibleToken" -import "ViewResolver" -import "MetadataViews" - import "Serialize" import "SerializationInterfaces" -access(all) -let admin = Test.getAccount(0x0000000000000007) -access(all) -let alice = Test.createAccount() +access(all) let admin = Test.getAccount(0x0000000000000007) +access(all) let alice = Test.createAccount() + +access(all) var mintedBlockHeight: UInt64 = 0 access(all) fun setup() { @@ -44,6 +40,12 @@ fun setup() { arguments: [] ) Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FungibleTokenMetadataViews", + path: "../contracts/standards/FungibleTokenMetadataViews.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) err = Test.deployContract( name: "ExampleNFT", path: "../contracts/example-assets/ExampleNFT.cdc", @@ -86,9 +88,16 @@ fun testSerializeNFTSucceeds() { ) Test.expect(mintResult, Test.beSucceeded()) + let heightResult = executeScript( + "../scripts/test/get_block_height.cdc", + [] + ) + mintedBlockHeight = heightResult.returnValue! as! UInt64 + let heightString = mintedBlockHeight.toString() + let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " - let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"54\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}" - let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"54\"}" + let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}") + let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"}") let idsResult = executeScript( "../scripts/nft/get_ids.cdc", @@ -105,15 +114,17 @@ fun testSerializeNFTSucceeds() { let serializedMetadata = serializeMetadataResult.returnValue! as! String - Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) - // Test.assertEqual(serializedMetadata, expectedPrefix.concat(altSuffix1)) + // Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) + Test.assertEqual(serializedMetadata, expectedPrefix.concat(altSuffix1)) } access(all) fun testOpenSeaMetadataSerializationStrategySucceeds() { + let heightString = mintedBlockHeight.toString() + let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " - let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"54\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}" - let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"54\"}" + let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}") + let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"}") let idsResult = executeScript( "../scripts/nft/get_ids.cdc", diff --git a/cadence/tests/Serialize_tests.cdc b/cadence/tests/serialize_tests.cdc similarity index 99% rename from cadence/tests/Serialize_tests.cdc rename to cadence/tests/serialize_tests.cdc index 91daa122..a7a1ccc9 100644 --- a/cadence/tests/Serialize_tests.cdc +++ b/cadence/tests/serialize_tests.cdc @@ -1,10 +1,6 @@ import Test import BlockchainHelpers -import "NonFungibleToken" -import "ViewResolver" -import "MetadataViews" - import "Serialize" import "SerializationInterfaces" From 7682f756f38ad586ec08204ebf395c7015d5d65e Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:19:59 -0500 Subject: [PATCH 18/39] minimize serialization utils by removing interfaces & strategies --- .../contracts/utils/DelegatedCOACaller.cdc | 137 ++++++++++ .../utils/SerializationInterfaces.cdc | 30 --- cadence/contracts/utils/Serialize.cdc | 24 -- cadence/contracts/utils/SerializeNFT.cdc | 56 +--- .../serialize_nft_from_open_sea_strategy.cdc | 21 -- .../scripts/serialize/serialize_nft_old.cdc | 239 ++++++++++++++++++ cadence/tests/serialize_nft_tests.cdc | 29 --- cadence/tests/serialize_tests.cdc | 7 - flow.json | 7 - local/normalize_coverage_report.sh | 1 - local/setup_emulator.2.sh | 1 - 11 files changed, 378 insertions(+), 174 deletions(-) create mode 100644 cadence/contracts/utils/DelegatedCOACaller.cdc delete mode 100644 cadence/contracts/utils/SerializationInterfaces.cdc delete mode 100644 cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc create mode 100644 cadence/scripts/serialize/serialize_nft_old.cdc diff --git a/cadence/contracts/utils/DelegatedCOACaller.cdc b/cadence/contracts/utils/DelegatedCOACaller.cdc new file mode 100644 index 00000000..f712792c --- /dev/null +++ b/cadence/contracts/utils/DelegatedCOACaller.cdc @@ -0,0 +1,137 @@ +import "FungibleToken" + +import "EVM" + +import "FlowEVMBridgeUtils" + +access(all) +contract DelegatedCOACaller { + + access(all) + let pathPrefix: String + + access(all) + event CallerCreated(address: EVM.EVMAddress, owner: Address?) + + access(all) + struct interface ICallParameters { + access(all) let to: EVM.EVMAddress + access(all) let data: [UInt8] + access(all) let gasLimit: UInt64 + access(all) let value: EVM.Balance + } + + access(all) + struct CallParameters : ICallParameters{ + access(all) let to: EVM.EVMAddress + access(all) let data: [UInt8] + access(all) let gasLimit: UInt64 + access(all) let value: EVM.Balance + + init( + to: EVM.EVMAddress, + data: [UInt8], + gasLimit: UInt64, + value: EVM.Balance + ) { + self.to = to + self.data = data + self.gasLimit = gasLimit + self.value = value + } + } + + access(all) + resource interface ICaller : EVM.Addressable { + access(all) + var pendingCall: {ICallParameters}? + + access(EVM.Owner | EVM.Call) + fun setPendingCall(_ parameters: {ICallParameters}) { + pre { + self.pendingCall == nil: "Call already pending" + } + } + + access(EVM.Owner | EVM.Call) + fun reset() { + self.pendingCall = nil + } + + access(all) + fun executeCall(): EVM.Result { + pre { + self.pendingCall != nil: "No pending call found" + } + post { + self.pendingCall == nil + } + } + } + + access(all) + resource Caller : ICaller, EVM.Addressable { + access(self) + let coaCapability: Capability + access(all) + var pendingCall: {ICallParameters}? + + init(coaCapability: Capability) { + pre { + coaCapability.borrow() != nil: "Invalid COA Capability" + } + self.coaCapability = coaCapability + self.pendingCall = nil + } + + /// The EVM address of the associated CadenceOwnedAccount + access(all)caSt + view fun address(): EVM.EVMAddress { + return self.borrowCOA().address() + } + + access(all) + fun executeCall(): EVM.Result { + let callResult = self.borrowCOA().call( + to: self.pendingCall!.to, + data: self.pendingCall!.data, + gasLimit: self.pendingCall!.gasLimit, + value: self.pendingCall!.value + ) + self.reset() + return callResult + } + + access(EVM.Owner | EVM.Call) + fun setPendingCall(_ parameters: {ICallParameters}) { + self.pendingCall = parameters + } + + access(EVM.Owner | EVM.Call) + fun reset() { + self.pendingCall = nil + } + + access(self) + view fun borrowCOA(): auth(EVM.Call) &EVM.CadenceOwnedAccount { + return self.coaCapability.borrow() ?? panic("Invalid COA Capability") + } + } + + access(all) + fun createCaller(coaCapability: Capability): @Caller { + let caller <- create Caller(coaCapability: coaCapability) + emit CallerCreated(address: caller.address(), owner: coaCapability.borrow()!.owner?.address) + return <-caller + } + + access(all) + view fun deriveStoragePath(from coaAddress: EVM.EVMAddress): StoragePath? { + let addressHex = FlowEVMBridgeUtils.getEVMAddressAsHexString(address: coaAddress) + return StoragePath(identifier: self.pathPrefix.concat(addressHex)) + } + + init() { + self.pathPrefix = "delegatedCOACaller_" + } +} diff --git a/cadence/contracts/utils/SerializationInterfaces.cdc b/cadence/contracts/utils/SerializationInterfaces.cdc deleted file mode 100644 index 667982a5..00000000 --- a/cadence/contracts/utils/SerializationInterfaces.cdc +++ /dev/null @@ -1,30 +0,0 @@ -/// The contract defines an interface for serialization strategies that can be used to serialize the struct or resource -/// according to a specific format. -/// -access(all) contract SerializationInterfaces { - - /// A SerializationStrategy takes a reference to a SerializableResource or SerializableStruct and returns a - /// serialized representation of it. The strategy is responsible for determining the structure of the serialized - /// representation and the format of the serialized data. - /// - access(all) - struct interface SerializationStrategy { - /// Returns the types supported by the implementing strategy - /// - access(all) view fun getSupportedTypes(): [Type] { - return [] - } - - /// Returns serialized representation of the given resource according to the format of the implementing strategy - /// - access(all) fun serializeResource(_ r: &AnyResource): String? { - return nil - } - - /// Returns serialized representation of the given struct according to the format of the implementing strategy - /// - access(all) fun serializeStruct(_ s: AnyStruct): String? { - return nil - } - } -} diff --git a/cadence/contracts/utils/Serialize.cdc b/cadence/contracts/utils/Serialize.cdc index 9c73f430..19347bc1 100644 --- a/cadence/contracts/utils/Serialize.cdc +++ b/cadence/contracts/utils/Serialize.cdc @@ -2,8 +2,6 @@ import "ViewResolver" import "MetadataViews" import "NonFungibleToken" -import "SerializationInterfaces" - /// This contract is a utility for serializing primitive types, arrays, and common metadata mapping formats to JSON /// compatible strings. Also included are interfaces enabling custom serialization for structs and resources. /// @@ -12,28 +10,6 @@ import "SerializationInterfaces" access(all) contract Serialize { - /// A basic serialization strategy that supports serializing resources and structs to JSON-compatible strings. - /// - access(all) - struct JSONStringStrategy : SerializationInterfaces.SerializationStrategy { - /// Returns the types this stategy will attempt to serialize - /// - access(all) view fun getSupportedTypes(): [Type] { - return [Type<@AnyResource>(), Type()] - } - /// Returns the resource serialized on its identifier as an escaped JSON string - /// - access(all) fun serializeResource(_ r: &AnyResource): String? { - return Serialize.tryToJSONString(r.getType().identifier) - } - /// Returns the an escaped JSON string of the provided struct, calling through to Serialize.tryToJSONString - /// with the provided value - /// - access(all) fun serializeStruct(_ s: AnyStruct): String? { - return Serialize.tryToJSONString(s) - } - } - /// Method that returns a serialized representation of the given value or nil if the value is not serializable /// access(all) diff --git a/cadence/contracts/utils/SerializeNFT.cdc b/cadence/contracts/utils/SerializeNFT.cdc index 4b36a643..c519e3a2 100644 --- a/cadence/contracts/utils/SerializeNFT.cdc +++ b/cadence/contracts/utils/SerializeNFT.cdc @@ -2,65 +2,13 @@ import "ViewResolver" import "MetadataViews" import "NonFungibleToken" -import "SerializationInterfaces" import "Serialize" /// This contract defines methods for serializing NFT metadata as a JSON compatible string, according to the common -/// OpenSea metadata format. NFTs can be serialized by reference via contract methods or via the -/// OpenSeaMetadataSerializationStrategy struct. +/// OpenSea metadata format. NFTs and metadata views can be serialized by reference via contract methods. /// access(all) contract SerializeNFT { - /// This struct will serialize NFT metadata as a JSON-compatible URI according to the OpenSea metadata standard - /// - access(all) - struct OpenSeaMetadataSerializationStrategy : SerializationInterfaces.SerializationStrategy { - /// Returns the types this strategy is intended to serialize - /// - access(all) view fun getSupportedTypes(): [Type] { - return [ - Type<@{NonFungibleToken.NFT}>(), - Type(), - Type(), - Type() - ] - } - - /// Serializes the given NFT (as &AnyResource) as a JSON compatible string in the format of an - /// OpenSea-compatible metadata URI. If the given resource is not an NFT, this method returns nil. - /// - /// Reference: https://docs.opensea.io/docs/metadata-standards - /// - access(all) fun serializeResource(_ r: &AnyResource): String? { - if r.getType().isSubtype(of: Type<@{NonFungibleToken.NFT}>()) { - let nft = r as! &{NonFungibleToken.NFT} - return SerializeNFT.serializeNFTMetadataAsURI(nft) - } - return nil - } - - /// Serializes the given struct as a JSON compatible string in the format that conforms with overlapping values - /// expected by the OpenSea metadata standard. If the given struct is not a Display, NFTCollectionDisplay, or - /// Traits view, this method returns nil. - /// - access(all) fun serializeStruct(_ s: AnyStruct): String? { - switch s.getType() { - case Type(): - let view = s as! MetadataViews.NFTCollectionDisplay - return SerializeNFT.serializeNFTDisplay(nftDisplay: nil, collectionDisplay: view) - case Type(): - let view = s as! MetadataViews.Display - return SerializeNFT.serializeNFTDisplay(nftDisplay: view, collectionDisplay: nil) - case Type(): - let view = s as! MetadataViews.Traits - return SerializeNFT.serializeNFTTraitsAsAttributes(view) - default: - return nil - - } - } - } - /// Serializes the metadata (as a JSON compatible String) for a given NFT according to formats expected by EVM /// platforms like OpenSea. If you are a project owner seeking to expose custom traits on bridged NFTs and your /// Trait.value is not natively serializable, you can implement a custom serialization method with the @@ -115,7 +63,7 @@ access(all) contract SerializeNFT { /// \"name\": \"\", \"description\": \"\", \"image\": \"\", \"external_url\": \"\", /// access(all) - fun serializeNFTDisplay(nftDisplay: MetadataViews.Display?, collectionDisplay: MetadataViews.NFTCollectionDisplay?): String? { + fun serializeNFTDisplay(nftDisplay: MetadataViews.Display?, collectionDisplay: MetadataViews.NFTCollectionDisplay?, ): String? { // Return early if both values are nil if nftDisplay == nil && collectionDisplay == nil { return nil diff --git a/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc b/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc deleted file mode 100644 index 95b8d1e2..00000000 --- a/cadence/scripts/serialize/serialize_nft_from_open_sea_strategy.cdc +++ /dev/null @@ -1,21 +0,0 @@ -import "ViewResolver" -import "MetadataViews" -import "NonFungibleToken" - -import "SerializeNFT" - -access(all) -fun main(address: Address, storagePathIdentifier: String, id: UInt64): String? { - let storagePath = StoragePath(identifier: storagePathIdentifier) - ?? panic("Could not construct StoragePath from identifier") - if let collection = getAuthAccount(address).storage - .borrow<&{NonFungibleToken.Collection}>( - from: storagePath - ) { - if let nft = collection.borrowNFT(id) { - let strategy = SerializeNFT.OpenSeaMetadataSerializationStrategy() - return strategy.serializeResource(nft) - } - } - return nil -} diff --git a/cadence/scripts/serialize/serialize_nft_old.cdc b/cadence/scripts/serialize/serialize_nft_old.cdc new file mode 100644 index 00000000..810edfa4 --- /dev/null +++ b/cadence/scripts/serialize/serialize_nft_old.cdc @@ -0,0 +1,239 @@ +import ViewResolver from 0x631e88ae7f1d7c20 +import MetadataViews from 0x631e88ae7f1d7c20 +import NonFungibleToken from 0x631e88ae7f1d7c20 + +/// Defines the interface for a struct that returns a serialized representation of itself +/// +access(all) +struct interface SerializableStruct { + access(all) fun serialize(): String +} + +/// Method that returns a serialized representation of the given value or nil if the value is not serializable +/// +access(all) +fun tryToJSONString(_ value: AnyStruct): String? { + // Call serialize on the value if available + if value.getType().isSubtype(of: Type<{SerializableStruct}>()) { + return (value as! {SerializableStruct}).serialize() + } + // Recursively serialize array & return + if value.getType().isSubtype(of: Type<[AnyStruct]>()) { + return arrayToJSONString(value as! [AnyStruct]) + } + // Recursively serialize map & return + if value.getType().isSubtype(of: Type<{String: AnyStruct}>()) { + return dictToJSONString(dict: value as! {String: AnyStruct}, excludedNames: nil) + } + // Handle primitive types & optionals + switch value.getType() { + case Type(): + return "\"nil\"" + case Type(): + return "\"".concat(value as! String).concat("\"") + case Type(): + return "\"".concat(value as? String ?? "nil").concat("\"") + case Type(): + return "\"".concat((value as! Character).toString()).concat("\"") + case Type(): + return "\"".concat(value as! Bool ? "true" : "false").concat("\"") + case Type
(): + return "\"".concat((value as! Address).toString()).concat("\"") + case Type(): + return "\"".concat((value as? Address)?.toString() ?? "nil").concat("\"") + case Type(): + return "\"".concat((value as! Int8).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int16).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int32).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int64).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int128).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int256).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Int).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt8).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt16).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt32).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt64).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt128).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt256).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UInt).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word8).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word16).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word32).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word64).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word128).toString()).concat("\"") + case Type(): + return "\"".concat((value as! Word256).toString()).concat("\"") + case Type(): + return "\"".concat((value as! UFix64).toString()).concat("\"") + default: + return nil + } +} + +/// Method that returns a serialized representation of the given array or nil if the value is not serializable +/// +access(all) +fun arrayToJSONString(_ arr: [AnyStruct]): String? { + var serializedArr = "[" + for i, element in arr { + let serializedElement = tryToJSONString(element) + if serializedElement == nil { + return nil + } + serializedArr = serializedArr.concat(serializedElement!) + if i < arr.length - 1 { + serializedArr = serializedArr.concat(", ") + } + } + return serializedArr.concat("]") +} + +/// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not +/// serializable. The interface here is largely the same as as the `MetadataViews.dictToTraits` method, though here +/// a JSON-compatible String is returned instead of a `Traits` array. +/// +access(all) +fun dictToJSONString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { + if excludedNames != nil { + for k in excludedNames! { + dict.remove(key: k) + } + } + var serializedDict = "{" + for i, key in dict.keys { + let serializedValue = tryToJSONString(dict[key]!) + if serializedValue == nil { + return nil + } + serializedDict = serializedDict.concat(tryToJSONString(key)!).concat(": ").concat(serializedValue!) + if i < dict.length - 1 { + serializedDict = serializedDict.concat(", ") + } + } + return serializedDict.concat("}") +} + +/// Serializes the metadata (as a JSON compatible String) for a given NFT according to formats expected by EVM +/// platforms like OpenSea. If you are a project owner seeking to expose custom traits on bridged NFTs and your +/// Trait.value is not natively serializable, you can implement a custom serialization method with the +/// `{SerializableStruct}` interface's `serialize` method. +/// +/// REF: https://github.com/ethereum/ercs/blob/master/ERCS/erc-721.md +/// REF: https://github.com/ethereum/ercs/blob/master/ERCS/erc-1155.md#erc-1155-metadata-uri-json-schema +/// REF: https://docs.opensea.io/docs/metadata-standards +/// +access(all) +fun serializeNFTMetadata(_ nft: &{MetadataViews.Resolver}): String { + // if nft.getType().isSubtype(of: Type<@{SerializableResource}>()) { + // let serializable = nft as! &{SerializableResource} + // return serializable.serialize() + // } + let display = serializeNFTDisplay(nft) + let attributes = serializeNFTTraitsAsAttributes(nft) + if display == nil && attributes == nil { + return "" + } + var serializedMetadata= "data:application/json;utf8,{" + if display != nil { + serializedMetadata = serializedMetadata.concat(display!) + } + if display != nil && attributes != nil { + serializedMetadata = serializedMetadata.concat(", ") + } + if attributes != nil { + serializedMetadata = serializedMetadata.concat(attributes!) + } + return serializedMetadata.concat("}") +} + +/// Serializes the display & collection display views of a given NFT as a JSON compatible string +/// +access(all) +fun serializeNFTDisplay(_ nft: &{MetadataViews.Resolver}): String? { + // Resolve Display & NFTCollection Display view, returning early if neither are found + let nftDisplay: MetadataViews.Display? = nft.resolveView(Type()) as! MetadataViews.Display? + let collectionDisplay: MetadataViews.NFTCollectionDisplay? = nft.resolveView(Type()) as! MetadataViews.NFTCollectionDisplay? + if nftDisplay == nil && collectionDisplay == nil { + return nil + } + // Initialize the JSON fields + let name = "\"name\": " + let description = "\"description\": " + let image = "\"image\": " + var serializedResult = "" + // Append results from the Display view to the serialized JSON compatible string + if nftDisplay != nil { + serializedResult = serializedResult.concat(name).concat(tryToJSONString(nftDisplay!.name)!).concat(", ") + .concat(description).concat(tryToJSONString(nftDisplay!.description)!).concat(", ") + .concat(image).concat(tryToJSONString(nftDisplay!.thumbnail.uri())!) + } + // Append a comma if both Display & NFTCollection Display views are present + if nftDisplay != nil && collectionDisplay != nil { + serializedResult = serializedResult.concat(", ") + } + // Serialize the external URL from the NFTCollection Display view & return + let externalURL = "\"external_url\": " + if collectionDisplay != nil { + serializedResult = serializedResult.concat(externalURL).concat(tryToJSONString(collectionDisplay!.externalURL.url)!) + } + return serializedResult +} + +/// Serializes a given NFT's Traits view as a JSON compatible string. If a given Trait is not serializable, it is +/// skipped and not included in the serialized result. If you are a project owner seeking to expose custom traits +/// on bridged NFTs and your Trait.value is not natively serializable, you can implement a custom serialization +/// method with the `{SerializableStruct}` interface's `serialize` method. +/// +access(all) +fun serializeNFTTraitsAsAttributes(_ nft: &{MetadataViews.Resolver}): String? { + // Get the Traits view from the NFT, returning early if no traits are found + let traits = nft.resolveView(Type()) as! MetadataViews.Traits? + if traits == nil { + return nil + } + + // Serialize each trait as an attribute, building the serialized JSON compatible string + var serializedResult = "\"attributes\": [" + for i, trait in traits!.traits { + let value = tryToJSONString(trait.value) + if value == nil { + continue + } + serializedResult = serializedResult.concat("{") + .concat("\"trait_type\": ").concat(tryToJSONString(trait.name)!) + .concat(", \"value\": ").concat(value!) + .concat("}") + if i < traits!.traits.length - 1 { + serializedResult = serializedResult.concat(",") + } + } + return serializedResult.concat("]") +} + +access(all) +fun main(address: Address, storagePathIdentifier: String, id: UInt64): String? { + let storagePath = StoragePath(identifier: storagePathIdentifier)! + if let collection = getAuthAccount(address).borrow<&{MetadataViews.ResolverCollection}>(from: storagePath) { + let nft = collection.borrowViewResolver(id: id) as &{MetadataViews.Resolver} + return serializeNFTMetadata(nft) + } + return nil +} diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index 33e392d7..caf2b1e8 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -2,7 +2,6 @@ import Test import BlockchainHelpers import "Serialize" -import "SerializationInterfaces" access(all) let admin = Test.getAccount(0x0000000000000007) access(all) let alice = Test.createAccount() @@ -52,12 +51,6 @@ fun setup() { arguments: [] ) Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "SerializationInterfaces", - path: "../contracts/utils/SerializationInterfaces.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) err = Test.deployContract( name: "Serialize", path: "../contracts/utils/Serialize.cdc", @@ -117,25 +110,3 @@ fun testSerializeNFTSucceeds() { // Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) Test.assertEqual(serializedMetadata, expectedPrefix.concat(altSuffix1)) } - -access(all) -fun testOpenSeaMetadataSerializationStrategySucceeds() { - let heightString = mintedBlockHeight.toString() - - let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " - let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}") - let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"}") - - let idsResult = executeScript( - "../scripts/nft/get_ids.cdc", - [alice.address, "cadenceExampleNFTCollection"] - ) - Test.expect(idsResult, Test.beSucceeded()) - let ids = idsResult.returnValue! as! [UInt64] - - let serializeMetadataResult = executeScript( - "../scripts/serialize/serialize_nft_from_open_sea_strategy.cdc", - [alice.address, "cadenceExampleNFTCollection", ids[0]] - ) - Test.expect(serializeMetadataResult, Test.beSucceeded()) -} diff --git a/cadence/tests/serialize_tests.cdc b/cadence/tests/serialize_tests.cdc index a7a1ccc9..b0e32a19 100644 --- a/cadence/tests/serialize_tests.cdc +++ b/cadence/tests/serialize_tests.cdc @@ -2,7 +2,6 @@ import Test import BlockchainHelpers import "Serialize" -import "SerializationInterfaces" access(all) let admin = Test.getAccount(0x0000000000000007) @@ -40,12 +39,6 @@ fun setup() { arguments: [] ) Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "SerializationInterfaces", - path: "../contracts/utils/SerializationInterfaces.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) err = Test.deployContract( name: "Serialize", path: "../contracts/utils/Serialize.cdc", diff --git a/flow.json b/flow.json index 11422490..0b48e44a 100644 --- a/flow.json +++ b/flow.json @@ -149,13 +149,6 @@ "emulator": "f8d6e0586b0a20c7" } }, - "SerializationInterfaces": { - "source": "./cadence/contracts/utils/SerializationInterfaces.cdc", - "aliases": { - "emulator": "f8d6e0586b0a20c7", - "testing": "0000000000000007" - } - }, "Serialize": { "source": "./cadence/contracts/utils/Serialize.cdc", "aliases": { diff --git a/local/normalize_coverage_report.sh b/local/normalize_coverage_report.sh index 8de7ee5f..37fc2917 100644 --- a/local/normalize_coverage_report.sh +++ b/local/normalize_coverage_report.sh @@ -1,3 +1,2 @@ -sed -i 's/A.0000000000000007.SerializationInterfaces/cadence\contracts\/SerializationInterfaces.cdc/' coverage.lcov sed -i 's/A.0000000000000007.Serialize/cadence\/contracts\/utils\/Serialize.cdc/' coverage.lcov sed -i 's/A.0000000000000007.SerializeNFT/cadence\contracts\/SerializeNFT.cdc/' coverage.lcov \ No newline at end of file diff --git a/local/setup_emulator.2.sh b/local/setup_emulator.2.sh index 17b19c66..4143ef95 100644 --- a/local/setup_emulator.2.sh +++ b/local/setup_emulator.2.sh @@ -11,7 +11,6 @@ flow transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_ flow accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc # Deploy Serialization Utils -flow accounts add-contract ./cadence/contracts/utils/SerializationInterfaces.cdc flow accounts add-contract ./cadence/contracts/utils/Serialize.cdc flow accounts add-contract ./cadence/contracts/utils/SerializeNFT.cdc From d49f49ff9bea7b07153999c6847f07667005c230 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:58:28 -0500 Subject: [PATCH 19/39] fix NFT serialization, add test cases & add contract URI serialization on deployERC721 --- cadence/contracts/bridge/FlowEVMBridge.cdc | 25 ++++++-- cadence/contracts/utils/SerializeNFT.cdc | 44 +++++++------- cadence/tests/serialize_nft_tests.cdc | 70 +++++++++++++++++++++- 3 files changed, 110 insertions(+), 29 deletions(-) diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index f63be6f5..ff336bd7 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -143,7 +143,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { if let metadata = token.resolveView(Type()) as! CrossVMNFT.EVMBridgedMetadata? { uri = metadata.uri.uri() } else { - // Otherwise, serialize the NFT using OpenSea Metadata strategy + // Otherwise, serialize the NFT uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT}) } @@ -416,13 +416,26 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { // Borrow the ViewResolver to attempt to resolve the EVMBridgedMetadata view let viewResolver = getAccount(cadenceAddress).contracts.borrow<&{ViewResolver}>(name: name)! var contractURI = "" - if let bridgedMetadata = viewResolver.resolveContractView( + // Try to resolve the EVMBridgedMetadata + let bridgedMetadata = viewResolver.resolveContractView( resourceType: forNFTType, viewType: Type() - ) as! CrossVMNFT.EVMBridgedMetadata? { - name = bridgedMetadata.name - symbol = bridgedMetadata.symbol - contractURI = bridgedMetadata.uri.uri() + ) as! CrossVMNFT.EVMBridgedMetadata? + // Default to project-defined URI if available + if bridgedMetadata != nil { + name = bridgedMetadata!.name + symbol = bridgedMetadata!.symbol + contractURI = bridgedMetadata!.uri.uri() + } else { + // Otherwise, serialize collection-level NFTCollectionDisplay + if let collectionDisplay = viewResolver.resolveContractView( + resourceType: forNFTType, + viewType: Type() + ) as! MetadataViews.NFTCollectionDisplay? { + name = collectionDisplay.name + let serializedDisplay = SerializeNFT.serializeFromDisplays(nftDisplay: nil, collectionDisplay: collectionDisplay)! + contractURI = "data:application/json;ascii,{".concat(serializedDisplay).concat("}") + } } // Call to the factory contract to deploy an ERC721 diff --git a/cadence/contracts/utils/SerializeNFT.cdc b/cadence/contracts/utils/SerializeNFT.cdc index c519e3a2..c8a97501 100644 --- a/cadence/contracts/utils/SerializeNFT.cdc +++ b/cadence/contracts/utils/SerializeNFT.cdc @@ -30,7 +30,7 @@ access(all) contract SerializeNFT { // Serialize the display values from the NFT's Display & NFTCollectionDisplay views let nftDisplay = nft.resolveView(Type()) as! MetadataViews.Display? let collectionDisplay = nft.resolveView(Type()) as! MetadataViews.NFTCollectionDisplay? - let display = self.serializeNFTDisplay(nftDisplay: nftDisplay, collectionDisplay: collectionDisplay) + let display = self.serializeFromDisplays(nftDisplay: nftDisplay, collectionDisplay: collectionDisplay) // Get the Traits view from the NFT, returning early if no traits are found let traits = nft.resolveView(Type()) as! MetadataViews.Traits? @@ -41,7 +41,7 @@ access(all) contract SerializeNFT { return "" } // Init the data format prefix & concatenate the serialized display & attributes - var serializedMetadata= "data:application/json;ascii,{" + var serializedMetadata = "data:application/json;ascii,{" if display != nil { serializedMetadata = serializedMetadata.concat(display!) } @@ -49,21 +49,24 @@ access(all) contract SerializeNFT { serializedMetadata = serializedMetadata.concat(", ") } if attributes != nil { - serializedMetadata = serializedMetadata.concat(attributes!) + serializedMetadata = serializedMetadata.concat(attributes) } return serializedMetadata.concat("}") } - /// Serializes the display & collection display views of a given NFT as a JSON compatible string + /// Serializes the display & collection display views of a given NFT as a JSON compatible string. If nftDisplay is + /// present, the value is returned as token-level metadata. If nftDisplay is nil and collectionDisplay is present, + /// the value is returned as contract-level metadata. If both values are nil, nil is returned. /// /// @param nftDisplay: The NFT's Display view from which values `name`, `description`, and `thumbnail` are serialized /// @param collectionDisplay: The NFT's NFTCollectionDisplay view from which the `externalURL` is serialized /// - /// @returns: A JSON compatible string containing the serialized display & collection display views as: - /// \"name\": \"\", \"description\": \"\", \"image\": \"\", \"external_url\": \"\", + /// @returns: A JSON compatible string containing the serialized display & collection display views as either: + /// \"name\": \"\", \"description\": \"\", \"image\": \"\", \"external_url\": \"\", + /// \"name\": \"\", \"description\": \"\", \"image\": \"\", \"external_link\": \"\", /// access(all) - fun serializeNFTDisplay(nftDisplay: MetadataViews.Display?, collectionDisplay: MetadataViews.NFTCollectionDisplay?, ): String? { + fun serializeFromDisplays(nftDisplay: MetadataViews.Display?, collectionDisplay: MetadataViews.NFTCollectionDisplay?): String? { // Return early if both values are nil if nftDisplay == nil && collectionDisplay == nil { return nil @@ -74,33 +77,32 @@ access(all) contract SerializeNFT { let description = "\"description\": " let image = "\"image\": " let externalURL = "\"external_url\": " + let externalLink = "\"external_link\": " var serializedResult = "" - // Append results from the Display view to the serialized JSON compatible string + // Append results from the token-level Display view to the serialized JSON compatible string if nftDisplay != nil { serializedResult = serializedResult .concat(name).concat(Serialize.tryToJSONString(nftDisplay!.name)!).concat(", ") .concat(description).concat(Serialize.tryToJSONString(nftDisplay!.description)!).concat(", ") .concat(image).concat(Serialize.tryToJSONString(nftDisplay!.thumbnail.uri())!) - // Return here if collectionDisplay is not present - if collectionDisplay == nil { - return serializedResult + // Append the `externa_url` value from NFTCollectionDisplay view if present + if collectionDisplay != nil { + return serializedResult.concat(", ") + .concat(externalURL).concat(Serialize.tryToJSONString(collectionDisplay!.externalURL.url)!) } } - // Append a comma if both Display & NFTCollection Display views are present - if nftDisplay != nil { - serializedResult = serializedResult.concat(", ") - } else { - // Otherwise, append the name & description fields from the NFTCollectionDisplay view, foregoing image - serializedResult = serializedResult - .concat(name).concat(Serialize.tryToJSONString(collectionDisplay!.name)!).concat(", ") - .concat(description).concat(Serialize.tryToJSONString(collectionDisplay!.description)!).concat(", ") + if collectionDisplay == nil { + return serializedResult } + // Without token-level view, serialize as contract-level metadata return serializedResult - .concat(externalURL) - .concat(Serialize.tryToJSONString(collectionDisplay!.externalURL.url)!) + .concat(name).concat(Serialize.tryToJSONString(collectionDisplay!.name)!).concat(", ") + .concat(description).concat(Serialize.tryToJSONString(collectionDisplay!.description)!).concat(", ") + .concat(image).concat(Serialize.tryToJSONString(collectionDisplay!.squareImage.file.uri())!).concat(", ") + .concat(externalLink).concat(Serialize.tryToJSONString(collectionDisplay!.externalURL.url)!) } /// Serializes given Traits view as a JSON compatible string. If a given Trait is not serializable, it is skipped diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index caf2b1e8..efd97991 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -1,7 +1,10 @@ import Test import BlockchainHelpers +import "MetadataViews" + import "Serialize" +import "SerializeNFT" access(all) let admin = Test.getAccount(0x0000000000000007) access(all) let alice = Test.createAccount() @@ -107,6 +110,69 @@ fun testSerializeNFTSucceeds() { let serializedMetadata = serializeMetadataResult.returnValue! as! String - // Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) - Test.assertEqual(serializedMetadata, expectedPrefix.concat(altSuffix1)) + Test.assertEqual(true, serializedMetadata == expectedPrefix.concat(altSuffix1) || serializedMetadata == expectedPrefix.concat(altSuffix2)) +} + +// Returns nil when no displays are provided +access(all) +fun testSerializeNilDisplaysReturnsNil() { + let serializedResult = SerializeNFT.serializeFromDisplays(nftDisplay: nil, collectionDisplay: nil) + Test.assertEqual(nil, serializedResult) +} + +// Given just token-level Display, serialize as tokenURI format +access(all) +fun testSerializeNFTDisplaySucceeds() { + let display = MetadataViews.Display( + name: "NAME", + description: "NFT Description", + thumbnail: MetadataViews.HTTPFile(url: "https://flow.com/examplenft.jpg"), + ) + + let expected = "\"name\": \"NAME\", \"description\": \"NFT Description\", \"image\": \"https://flow.com/examplenft.jpg\"" + + let serializedResult = SerializeNFT.serializeFromDisplays(nftDisplay: display, collectionDisplay: nil) + Test.assertEqual(expected, serializedResult!) +} + +// Given just token-level Display, serialize as contractURI format +access(all) +fun testSerializeNFTCollectionDisplaySucceeds() { + let collectionDisplay = MetadataViews.NFTCollectionDisplay( + name: "NAME", + description: "NFT Description", + externalURL: MetadataViews.ExternalURL("https://flow.com"), + squareImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://flow.com/square_image.jpg"), mediaType: "image"), + bannerImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://flow.com/square_image.jpg"), mediaType: "image"), + socials: {} + ) + + let expected = "\"name\": \"NAME\", \"description\": \"NFT Description\", \"image\": \"https://flow.com/square_image.jpg\", \"external_link\": \"https://flow.com\"" + + let serializedResult = SerializeNFT.serializeFromDisplays(nftDisplay: nil, collectionDisplay: collectionDisplay) + Test.assertEqual(expected, serializedResult!) +} + +// Given bol token- & contract-level Displays, serialize as tokenURI format +access(all) +fun testSerializeBothDisplaysSucceeds() { + let nftDisplay = MetadataViews.Display( + name: "NAME", + description: "NFT Description", + thumbnail: MetadataViews.HTTPFile(url: "https://flow.com/examplenft.jpg"), + ) + + let collectionDisplay = MetadataViews.NFTCollectionDisplay( + name: "NAME", + description: "NFT Description", + externalURL: MetadataViews.ExternalURL("https://flow.com"), + squareImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://flow.com/square_image.jpg"), mediaType: "image"), + bannerImage: MetadataViews.Media(file: MetadataViews.HTTPFile(url: "https://flow.com/square_image.jpg"), mediaType: "image"), + socials: {} + ) + + let expected = "\"name\": \"NAME\", \"description\": \"NFT Description\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://flow.com\"" + + let serializedResult = SerializeNFT.serializeFromDisplays(nftDisplay: nftDisplay, collectionDisplay: collectionDisplay) + Test.assertEqual(expected, serializedResult!) } From c1b611d5a67acc1606bb5f4c8b9988b89b8e8d22 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:59:50 -0500 Subject: [PATCH 20/39] add test/get_block_height script --- cadence/scripts/test/get_block_height.cdc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cadence/scripts/test/get_block_height.cdc diff --git a/cadence/scripts/test/get_block_height.cdc b/cadence/scripts/test/get_block_height.cdc new file mode 100644 index 00000000..cd95b66d --- /dev/null +++ b/cadence/scripts/test/get_block_height.cdc @@ -0,0 +1,4 @@ +access(all) +fun main(): UInt64 { + return getCurrentBlock().height +} \ No newline at end of file From b5e3d6b32d96086ccf4e6df390a5db53d2579159 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 22:20:06 -0500 Subject: [PATCH 21/39] fix foundry_test ci failures --- cadence/contracts/bridge/FlowEVMBridge.cdc | 2 +- foundry.toml | 1 - solidity/test/FlowBridgeFactory.t.sol | 9 +++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index ff336bd7..2b22f681 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -146,7 +146,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { // Otherwise, serialize the NFT uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT}) } - + // Lock the NFT & calculate the storage used by the NFT let storageUsed = FlowEVMBridgeNFTEscrow.lockNFT(<-token) // Calculate the bridge fee on current rates diff --git a/foundry.toml b/foundry.toml index eff86f58..2b5e79b5 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,6 +4,5 @@ out = "./solidity/out" libs = ["./solidity/lib"] script = "./solidity/script" test = "./solidity/test" -eth_rpc_url = "http://127.0.0.1:8545" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/solidity/test/FlowBridgeFactory.t.sol b/solidity/test/FlowBridgeFactory.t.sol index 08c6c5b1..05d6e73a 100644 --- a/solidity/test/FlowBridgeFactory.t.sol +++ b/solidity/test/FlowBridgeFactory.t.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; -import {Test, console2} from "forge-std/Test.sol"; +import {Test} from "forge-std/Test.sol"; + import {FlowBridgeFactory} from "../src/FlowBridgeFactory.sol"; import {FlowBridgedERC721} from "../src/FlowBridgedERC721.sol"; contract FlowBridgeFactoryTest is Test { - FlowBridgeFactory public factory; - FlowBridgedERC721 public deployedERC721Contract; + FlowBridgeFactory internal factory; + FlowBridgedERC721 internal deployedERC721Contract; string name; string symbol; @@ -16,7 +17,7 @@ contract FlowBridgeFactoryTest is Test { string contractURI; address deployedERC721Address; - function setUp() public { + function setUp() public virtual { factory = new FlowBridgeFactory(); name = "name"; symbol = "symbol"; From 67228cff70f4a667466ad7f44ee9d3ce41cec8d2 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:04:58 -0500 Subject: [PATCH 22/39] update serialization serialized json data prefix --- cadence/contracts/bridge/FlowEVMBridge.cdc | 2 +- cadence/contracts/utils/SerializeNFT.cdc | 2 +- cadence/tests/serialize_nft_tests.cdc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cadence/contracts/bridge/FlowEVMBridge.cdc b/cadence/contracts/bridge/FlowEVMBridge.cdc index 2b22f681..48608972 100644 --- a/cadence/contracts/bridge/FlowEVMBridge.cdc +++ b/cadence/contracts/bridge/FlowEVMBridge.cdc @@ -434,7 +434,7 @@ contract FlowEVMBridge : IFlowEVMNFTBridge { ) as! MetadataViews.NFTCollectionDisplay? { name = collectionDisplay.name let serializedDisplay = SerializeNFT.serializeFromDisplays(nftDisplay: nil, collectionDisplay: collectionDisplay)! - contractURI = "data:application/json;ascii,{".concat(serializedDisplay).concat("}") + contractURI = "data:application/json;utf8,{".concat(serializedDisplay).concat("}") } } diff --git a/cadence/contracts/utils/SerializeNFT.cdc b/cadence/contracts/utils/SerializeNFT.cdc index c8a97501..42cd631e 100644 --- a/cadence/contracts/utils/SerializeNFT.cdc +++ b/cadence/contracts/utils/SerializeNFT.cdc @@ -41,7 +41,7 @@ access(all) contract SerializeNFT { return "" } // Init the data format prefix & concatenate the serialized display & attributes - var serializedMetadata = "data:application/json;ascii,{" + var serializedMetadata = "data:application/json;utf8,{" if display != nil { serializedMetadata = serializedMetadata.concat(display!) } diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index efd97991..ef0e1bbc 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -91,7 +91,7 @@ fun testSerializeNFTSucceeds() { mintedBlockHeight = heightResult.returnValue! as! UInt64 let heightString = mintedBlockHeight.toString() - let expectedPrefix = "data:application/json;ascii,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " + let expectedPrefix = "data:application/json;utf8,{\"name\": \"ExampleNFT\", \"description\": \"Example NFT Collection\", \"image\": \"https://flow.com/examplenft.jpg\", \"external_url\": \"https://example-nft.onflow.org\", " let altSuffix1 = "\"attributes\": [{\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"},{\"trait_type\": \"foo\", \"value\": \"nil\"}]}") let altSuffix2 = "\"attributes\": [{\"trait_type\": \"foo\", \"value\": \"nil\"}]}, {\"trait_type\": \"mintedBlock\", \"value\": \"".concat(heightString).concat("\"}") From ec53d0025950295b74dff55f5be1cbacecf05fd6 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 20 Mar 2024 19:36:14 +0200 Subject: [PATCH 23/39] Update flow-cli version used in CI workflow --- .github/workflows/cadence_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml index 69caf3c9..ee4a3111 100644 --- a/.github/workflows/cadence_test.yml +++ b/.github/workflows/cadence_test.yml @@ -19,7 +19,7 @@ jobs: restore-keys: | ${{ runner.os }}-go- - name: Install Flow CLI - run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.12.0-cadence-v1.0.0-M8-2 + run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.15.0-cadence-v1.0.0-preview.12 - name: Flow CLI Version run: flow version - name: Update PATH From cf5feb08949e36daed8aeaa565d139b4e2eab21e Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 13:07:08 -0500 Subject: [PATCH 24/39] remove unnecessary script --- .../scripts/serialize/serialize_nft_old.cdc | 239 ------------------ 1 file changed, 239 deletions(-) delete mode 100644 cadence/scripts/serialize/serialize_nft_old.cdc diff --git a/cadence/scripts/serialize/serialize_nft_old.cdc b/cadence/scripts/serialize/serialize_nft_old.cdc deleted file mode 100644 index 810edfa4..00000000 --- a/cadence/scripts/serialize/serialize_nft_old.cdc +++ /dev/null @@ -1,239 +0,0 @@ -import ViewResolver from 0x631e88ae7f1d7c20 -import MetadataViews from 0x631e88ae7f1d7c20 -import NonFungibleToken from 0x631e88ae7f1d7c20 - -/// Defines the interface for a struct that returns a serialized representation of itself -/// -access(all) -struct interface SerializableStruct { - access(all) fun serialize(): String -} - -/// Method that returns a serialized representation of the given value or nil if the value is not serializable -/// -access(all) -fun tryToJSONString(_ value: AnyStruct): String? { - // Call serialize on the value if available - if value.getType().isSubtype(of: Type<{SerializableStruct}>()) { - return (value as! {SerializableStruct}).serialize() - } - // Recursively serialize array & return - if value.getType().isSubtype(of: Type<[AnyStruct]>()) { - return arrayToJSONString(value as! [AnyStruct]) - } - // Recursively serialize map & return - if value.getType().isSubtype(of: Type<{String: AnyStruct}>()) { - return dictToJSONString(dict: value as! {String: AnyStruct}, excludedNames: nil) - } - // Handle primitive types & optionals - switch value.getType() { - case Type(): - return "\"nil\"" - case Type(): - return "\"".concat(value as! String).concat("\"") - case Type(): - return "\"".concat(value as? String ?? "nil").concat("\"") - case Type(): - return "\"".concat((value as! Character).toString()).concat("\"") - case Type(): - return "\"".concat(value as! Bool ? "true" : "false").concat("\"") - case Type
(): - return "\"".concat((value as! Address).toString()).concat("\"") - case Type(): - return "\"".concat((value as? Address)?.toString() ?? "nil").concat("\"") - case Type(): - return "\"".concat((value as! Int8).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int16).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int32).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int64).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int128).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int256).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Int).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt8).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt16).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt32).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt64).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt128).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt256).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UInt).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word8).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word16).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word32).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word64).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word128).toString()).concat("\"") - case Type(): - return "\"".concat((value as! Word256).toString()).concat("\"") - case Type(): - return "\"".concat((value as! UFix64).toString()).concat("\"") - default: - return nil - } -} - -/// Method that returns a serialized representation of the given array or nil if the value is not serializable -/// -access(all) -fun arrayToJSONString(_ arr: [AnyStruct]): String? { - var serializedArr = "[" - for i, element in arr { - let serializedElement = tryToJSONString(element) - if serializedElement == nil { - return nil - } - serializedArr = serializedArr.concat(serializedElement!) - if i < arr.length - 1 { - serializedArr = serializedArr.concat(", ") - } - } - return serializedArr.concat("]") -} - -/// Method that returns a serialized representation of the given String-indexed mapping or nil if the value is not -/// serializable. The interface here is largely the same as as the `MetadataViews.dictToTraits` method, though here -/// a JSON-compatible String is returned instead of a `Traits` array. -/// -access(all) -fun dictToJSONString(dict: {String: AnyStruct}, excludedNames: [String]?): String? { - if excludedNames != nil { - for k in excludedNames! { - dict.remove(key: k) - } - } - var serializedDict = "{" - for i, key in dict.keys { - let serializedValue = tryToJSONString(dict[key]!) - if serializedValue == nil { - return nil - } - serializedDict = serializedDict.concat(tryToJSONString(key)!).concat(": ").concat(serializedValue!) - if i < dict.length - 1 { - serializedDict = serializedDict.concat(", ") - } - } - return serializedDict.concat("}") -} - -/// Serializes the metadata (as a JSON compatible String) for a given NFT according to formats expected by EVM -/// platforms like OpenSea. If you are a project owner seeking to expose custom traits on bridged NFTs and your -/// Trait.value is not natively serializable, you can implement a custom serialization method with the -/// `{SerializableStruct}` interface's `serialize` method. -/// -/// REF: https://github.com/ethereum/ercs/blob/master/ERCS/erc-721.md -/// REF: https://github.com/ethereum/ercs/blob/master/ERCS/erc-1155.md#erc-1155-metadata-uri-json-schema -/// REF: https://docs.opensea.io/docs/metadata-standards -/// -access(all) -fun serializeNFTMetadata(_ nft: &{MetadataViews.Resolver}): String { - // if nft.getType().isSubtype(of: Type<@{SerializableResource}>()) { - // let serializable = nft as! &{SerializableResource} - // return serializable.serialize() - // } - let display = serializeNFTDisplay(nft) - let attributes = serializeNFTTraitsAsAttributes(nft) - if display == nil && attributes == nil { - return "" - } - var serializedMetadata= "data:application/json;utf8,{" - if display != nil { - serializedMetadata = serializedMetadata.concat(display!) - } - if display != nil && attributes != nil { - serializedMetadata = serializedMetadata.concat(", ") - } - if attributes != nil { - serializedMetadata = serializedMetadata.concat(attributes!) - } - return serializedMetadata.concat("}") -} - -/// Serializes the display & collection display views of a given NFT as a JSON compatible string -/// -access(all) -fun serializeNFTDisplay(_ nft: &{MetadataViews.Resolver}): String? { - // Resolve Display & NFTCollection Display view, returning early if neither are found - let nftDisplay: MetadataViews.Display? = nft.resolveView(Type()) as! MetadataViews.Display? - let collectionDisplay: MetadataViews.NFTCollectionDisplay? = nft.resolveView(Type()) as! MetadataViews.NFTCollectionDisplay? - if nftDisplay == nil && collectionDisplay == nil { - return nil - } - // Initialize the JSON fields - let name = "\"name\": " - let description = "\"description\": " - let image = "\"image\": " - var serializedResult = "" - // Append results from the Display view to the serialized JSON compatible string - if nftDisplay != nil { - serializedResult = serializedResult.concat(name).concat(tryToJSONString(nftDisplay!.name)!).concat(", ") - .concat(description).concat(tryToJSONString(nftDisplay!.description)!).concat(", ") - .concat(image).concat(tryToJSONString(nftDisplay!.thumbnail.uri())!) - } - // Append a comma if both Display & NFTCollection Display views are present - if nftDisplay != nil && collectionDisplay != nil { - serializedResult = serializedResult.concat(", ") - } - // Serialize the external URL from the NFTCollection Display view & return - let externalURL = "\"external_url\": " - if collectionDisplay != nil { - serializedResult = serializedResult.concat(externalURL).concat(tryToJSONString(collectionDisplay!.externalURL.url)!) - } - return serializedResult -} - -/// Serializes a given NFT's Traits view as a JSON compatible string. If a given Trait is not serializable, it is -/// skipped and not included in the serialized result. If you are a project owner seeking to expose custom traits -/// on bridged NFTs and your Trait.value is not natively serializable, you can implement a custom serialization -/// method with the `{SerializableStruct}` interface's `serialize` method. -/// -access(all) -fun serializeNFTTraitsAsAttributes(_ nft: &{MetadataViews.Resolver}): String? { - // Get the Traits view from the NFT, returning early if no traits are found - let traits = nft.resolveView(Type()) as! MetadataViews.Traits? - if traits == nil { - return nil - } - - // Serialize each trait as an attribute, building the serialized JSON compatible string - var serializedResult = "\"attributes\": [" - for i, trait in traits!.traits { - let value = tryToJSONString(trait.value) - if value == nil { - continue - } - serializedResult = serializedResult.concat("{") - .concat("\"trait_type\": ").concat(tryToJSONString(trait.name)!) - .concat(", \"value\": ").concat(value!) - .concat("}") - if i < traits!.traits.length - 1 { - serializedResult = serializedResult.concat(",") - } - } - return serializedResult.concat("]") -} - -access(all) -fun main(address: Address, storagePathIdentifier: String, id: UInt64): String? { - let storagePath = StoragePath(identifier: storagePathIdentifier)! - if let collection = getAuthAccount(address).borrow<&{MetadataViews.ResolverCollection}>(from: storagePath) { - let nft = collection.borrowViewResolver(id: id) as &{MetadataViews.Resolver} - return serializeNFTMetadata(nft) - } - return nil -} From 1e8d16280c59cb68185d16ce2925028f84a615e4 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:21:04 -0500 Subject: [PATCH 25/39] update test comments --- cadence/tests/serialize_nft_tests.cdc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index ef0e1bbc..1000bb60 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -135,7 +135,7 @@ fun testSerializeNFTDisplaySucceeds() { Test.assertEqual(expected, serializedResult!) } -// Given just token-level Display, serialize as contractURI format +// Given just contract-level Display, serialize as contractURI format access(all) fun testSerializeNFTCollectionDisplaySucceeds() { let collectionDisplay = MetadataViews.NFTCollectionDisplay( From 94ccccbed3c11f4b2fc271309e25377ba2ef4492 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:09:21 -0500 Subject: [PATCH 26/39] add initial bridge test coverage --- cadence/tests/flow_evm_bridge_tests.cdc | 75 +++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 cadence/tests/flow_evm_bridge_tests.cdc diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc new file mode 100644 index 00000000..c9095273 --- /dev/null +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -0,0 +1,75 @@ +import Test +import BlockchainHelpers + +access(all) let serviceAccount = Test.serviceAccount() +access(all) let alice = Test.createAccount() + +access(all) let updatedEVMCodeHex = "696d706f72742043727970746f0a696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a61636365737328616c6c290a636f6e74726163742045564d207b0a0a202020202f2f20456e7469746c656d656e747320656e61626c696e672066696e65722d6772616e65642061636365737320636f6e74726f6c206f6e206120436164656e63654f776e65644163636f756e740a2020202061636365737328616c6c2920656e7469746c656d656e742056616c69646174650a2020202061636365737328616c6c2920656e7469746c656d656e742057697468647261770a2020202061636365737328616c6c2920656e7469746c656d656e742043616c6c0a2020202061636365737328616c6c2920656e7469746c656d656e74204465706c6f790a2020202061636365737328616c6c2920656e7469746c656d656e74204f776e65720a2020202061636365737328616c6c2920656e7469746c656d656e74204272696467650a0a2020202061636365737328616c6c290a202020206576656e7420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a205b55496e74383b2032305d290a0a202020202f2f2f2045564d4164647265737320697320616e2045564d2d636f6d70617469626c6520616464726573730a2020202061636365737328616c6c290a202020207374727563742045564d41646472657373207b0a0a20202020202020202f2f2f204279746573206f662074686520616464726573730a202020202020202061636365737328616c6c290a20202020202020206c65742062797465733a205b55496e74383b2032305d0a0a20202020202020202f2f2f20436f6e737472756374732061206e65772045564d20616464726573732066726f6d2074686520676976656e206279746520726570726573656e746174696f6e0a20202020202020207669657720696e69742862797465733a205b55496e74383b2032305d29207b0a20202020202020202020202073656c662e6279746573203d2062797465730a20202020202020207d0a0a20202020202020202f2f2f2042616c616e6365206f662074686520616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a2020202020202020202020206c65742062616c616e6365203d20496e7465726e616c45564d2e62616c616e6365280a20202020202020202020202020202020616464726573733a2073656c662e62797465730a202020202020202020202020290a20202020202020202020202072657475726e2042616c616e6365286174746f666c6f773a2062616c616e6365290a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207374727563742042616c616e6365207b0a0a20202020202020202f2f2f205468652062616c616e636520696e206174746f2d464c4f570a20202020202020202f2f2f204174746f2d464c4f572069732074686520736d616c6c6573742064656e6f6d696e6174696f6e206f6620464c4f5720283165313820464c4f57290a20202020202020202f2f2f2074686174206973207573656420746f2073746f7265206163636f756e742062616c616e63657320696e736964652045564d0a20202020202020202f2f2f2073696d696c617220746f207468652077617920574549206973207573656420746f2073746f72652045544820646976697369626c6520746f20313820646563696d616c20706c616365732e0a202020202020202061636365737328616c6c290a2020202020202020766172206174746f666c6f773a2055496e740a0a20202020202020202f2f2f20436f6e737472756374732061206e65772062616c616e63650a202020202020202061636365737328616c6c290a20202020202020207669657720696e6974286174746f666c6f773a2055496e7429207b0a20202020202020202020202073656c662e6174746f666c6f77203d206174746f666c6f770a20202020202020207d0a0a20202020202020202f2f2f2053657473207468652062616c616e636520627920612055466978363420283820646563696d616c20706f696e7473292c2074686520666f726d61740a20202020202020202f2f2f2074686174206973207573656420696e20436164656e636520746f2073746f726520464c4f5720746f6b656e732e0a202020202020202061636365737328616c6c290a202020202020202066756e20736574464c4f5728666c6f773a20554669783634297b0a20202020202020202020202073656c662e6174746f666c6f77203d20496e7465726e616c45564d2e63617374546f4174746f464c4f572862616c616e63653a20666c6f77290a20202020202020207d0a0a20202020202020202f2f2f204361737473207468652062616c616e636520746f2061205546697836342028726f756e64696e6720646f776e290a20202020202020202f2f2f205761726e696e67212063617374696e6720612062616c616e636520746f20612055466978363420776869636820737570706f7274732061206c6f776572206c6576656c206f6620707265636973696f6e0a20202020202020202f2f2f20283820646563696d616c20706f696e747320696e20636f6d7061726520746f20313829206d6967687420726573756c7420696e20726f756e64696e6720646f776e206572726f722e0a20202020202020202f2f2f205573652074686520746f4174746f466c6f772066756e6374696f6e20696620796f752063617265206e656564206d6f72652061636375726163792e0a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e464c4f5728293a20554669783634207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63617374546f464c4f572862616c616e63653a2073656c662e6174746f666c6f77290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e73207468652062616c616e636520696e204174746f2d464c4f570a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e4174746f464c4f5728293a2055496e74207b0a20202020202020202020202072657475726e2073656c662e6174746f666c6f770a20202020202020207d0a202020207d0a0a202020202f2f2f207265706f7274732074686520737461747573206f662065766d20657865637574696f6e2e0a2020202061636365737328616c6c2920656e756d205374617475733a2055496e7438207b0a20202020202020202f2f2f2069732028726172656c79292072657475726e6564207768656e2073746174757320697320756e6b6e6f776e0a20202020202020202f2f2f20616e6420736f6d657468696e672068617320676f6e6520766572792077726f6e672e0a202020202020202061636365737328616c6c29206361736520756e6b6e6f776e0a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206661696c6564206174207468652076616c69646174696f6e20737465702028652e672e206e6f6e6365206d69736d61746368292e0a20202020202020202f2f2f20416e20696e76616c6964207472616e73616374696f6e2f63616c6c2069732072656a656374656420746f2062652065786563757465640a20202020202020202f2f2f206f7220626520696e636c7564656420696e206120626c6f636b2e0a202020202020202061636365737328616c6c29206361736520696e76616c69640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c206275742074686520766d20686173207265706f7274656420616e206572726f722061730a20202020202020202f2f2f20746865206f7574636f6d65206f6620657865637574696f6e2028652e672e2072756e6e696e67206f7574206f6620676173292e0a20202020202020202f2f2f2041206661696c65642074782f63616c6c20697320696e636c7564656420696e206120626c6f636b2e0a20202020202020202f2f2f204e6f746520746861742072657375626d697373696f6e206f662061206661696c6564207472616e73616374696f6e20776f756c640a20202020202020202f2f2f20726573756c7420696e20696e76616c69642073746174757320696e20746865207365636f6e6420617474656d70742c20676976656e0a20202020202020202f2f2f20746865206e6f6e636520776f756c6420626520636f6d6520696e76616c69642e0a202020202020202061636365737328616c6c292063617365206661696c65640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c20616e64206e6f206572726f72206973207265706f727465642062792074686520766d2e0a202020202020202061636365737328616c6c292063617365207375636365737366756c0a202020207d0a0a202020202f2f2f207265706f72747320746865206f7574636f6d65206f662065766d207472616e73616374696f6e2f63616c6c20657865637574696f6e20617474656d70740a2020202061636365737328616c6c292073747275637420526573756c74207b0a20202020202020202f2f2f20737461747573206f662074686520657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c6574207374617475733a205374617475730a0a20202020202020202f2f2f206572726f7220636f646520286572726f7220636f6465207a65726f206d65616e73206e6f206572726f72290a202020202020202061636365737328616c6c290a20202020202020206c6574206572726f72436f64653a2055496e7436340a0a20202020202020202f2f2f2072657475726e732074686520616d6f756e74206f6620676173206d65746572656420647572696e670a20202020202020202f2f2f2065766d20657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c657420676173557365643a2055496e7436340a0a20202020202020202f2f2f2072657475726e7320746865206461746120746861742069732072657475726e65642066726f6d0a20202020202020202f2f2f207468652065766d20666f72207468652063616c6c2e20466f7220636f612e6465706c6f790a20202020202020202f2f2f2063616c6c732069742072657475726e73207468652061646472657373206279746573206f66207468650a20202020202020202f2f2f206e65776c79206465706c6f79656420636f6e74726163742e0a202020202020202061636365737328616c6c290a20202020202020206c657420646174613a205b55496e74385d0a0a2020202020202020696e6974280a2020202020202020202020207374617475733a205374617475732c0a2020202020202020202020206572726f72436f64653a2055496e7436342c0a202020202020202020202020676173557365643a2055496e7436342c0a202020202020202020202020646174613a205b55496e74385d0a202020202020202029207b0a20202020202020202020202073656c662e737461747573203d207374617475730a20202020202020202020202073656c662e6572726f72436f6465203d206572726f72436f64650a20202020202020202020202073656c662e67617355736564203d20676173557365640a20202020202020202020202073656c662e64617461203d20646174610a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204164647265737361626c65207b0a20202020202020202f2f2f205468652045564d20616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d416464726573730a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520436164656e63654f776e65644163636f756e743a204164647265737361626c65207b0a0a20202020202020206163636573732873656c66290a2020202020202020766172206164647265737342797465733a205b55496e74383b2032305d0a0a2020202020202020696e69742829207b0a2020202020202020202020202f2f206164647265737320697320696e697469616c6c792073657420746f207a65726f0a2020202020202020202020202f2f206275742075706461746564207468726f75676820696e697441646472657373206c617465720a2020202020202020202020202f2f207765206861766520746f20646f20746869732073696e6365207765206e656564207265736f75726365206964202875756964290a2020202020202020202020202f2f20746f2063616c63756c617465207468652045564d206164647265737320666f72207468697320636164656e6365206f776e6564206163636f756e740a20202020202020202020202073656c662e616464726573734279746573203d205b302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20305d0a20202020202020207d0a0a202020202020202061636365737328636f6e7472616374290a202020202020202066756e20696e697441646472657373286164647265737342797465733a205b55496e74383b2032305d29207b0a20202020202020202020202f2f206f6e6c7920616c6c6f7720736574206164647265737320666f72207468652066697273742074696d650a20202020202020202020202f2f20636865636b206164647265737320697320656d7074790a202020202020202020202020666f72206974656d20696e2073656c662e616464726573734279746573207b0a20202020202020202020202020202020617373657274286974656d203d3d20302c206d6573736167653a2022616464726573732062797465206973206e6f7420656d70747922290a2020202020202020202020207d0a202020202020202020202073656c662e616464726573734279746573203d206164647265737342797465730a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d41646472657373207b0a2020202020202020202020202f2f20416c77617973206372656174652061206e65772045564d4164647265737320696e7374616e63650a20202020202020202020202072657475726e2045564d416464726573732862797465733a2073656c662e616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f204765742062616c616e6365206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a20202020202020202020202072657475726e2073656c662e6164647265737328292e62616c616e636528290a20202020202020207d0a0a20202020202020202f2f2f204465706f736974732074686520676976656e207661756c7420696e746f2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369742866726f6d3a2040466c6f77546f6b656e2e5661756c7429207b0a202020202020202020202020496e7465726e616c45564d2e6465706f736974280a2020202020202020202020202020202066726f6d3a203c2d66726f6d2c0a20202020202020202020202020202020746f3a2073656c662e6164647265737342797465730a202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e7420626568696e6420616e20656e7469746c656d656e742c20616374696e672061732070726f6f66206f66206163636573730a2020202020202020616363657373284f776e6572207c2056616c6964617465290a2020202020202020766965772066756e2070726f7465637465644164647265737328293a2045564d41646472657373207b0a20202020202020202020202072657475726e2073656c662e6164647265737328290a20202020202020207d0a0a20202020202020202f2f2f20576974686472617773207468652062616c616e63652066726f6d2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a20202020202020202f2f2f204e6f7465207468617420616d6f756e747320736d616c6c6572207468616e2031306e4620283130652d38292063616e27742062652077697468647261776e0a20202020202020202f2f2f20676976656e207468617420466c6f7720546f6b656e205661756c747320757365205546697836347320746f2073746f72652062616c616e6365732e0a20202020202020202f2f2f2049662074686520676976656e2062616c616e636520636f6e76657273696f6e20746f2055466978363420726573756c747320696e0a20202020202020202f2f2f20726f756e64696e67206572726f722c20746869732066756e6374696f6e20776f756c64206661696c2e0a2020202020202020616363657373284f776e6572207c205769746864726177290a202020202020202066756e2077697468647261772862616c616e63653a2042616c616e6365293a2040466c6f77546f6b656e2e5661756c74207b0a2020202020202020202020206c6574207661756c74203c2d20496e7465726e616c45564d2e7769746864726177280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020616d6f756e743a2062616c616e63652e6174746f666c6f770a20202020202020202020202029206173212040466c6f77546f6b656e2e5661756c740a20202020202020202020202072657475726e203c2d7661756c740a20202020202020207d0a0a20202020202020202f2f2f204465706c6f7973206120636f6e747261637420746f207468652045564d20656e7669726f6e6d656e742e0a20202020202020202f2f2f2052657475726e73207468652061646472657373206f6620746865206e65776c79206465706c6f79656420636f6e74726163740a2020202020202020616363657373284f776e6572207c204465706c6f79290a202020202020202066756e206465706c6f79280a202020202020202020202020636f64653a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a2045564d41646472657373207b0a2020202020202020202020206c657420616464726573734279746573203d20496e7465726e616c45564d2e6465706c6f79280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020636f64653a20636f64652c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020290a20202020202020202020202072657475726e2045564d416464726573732862797465733a20616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f2043616c6c7320612066756e6374696f6e20776974682074686520676976656e20646174612e0a20202020202020202f2f2f2054686520657865637574696f6e206973206c696d697465642062792074686520676976656e20616d6f756e74206f66206761730a2020202020202020616363657373284f776e6572207c2043616c6c290a202020202020202066756e2063616c6c280a202020202020202020202020746f3a2045564d416464726573732c0a202020202020202020202020646174613a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a20526573756c74207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63616c6c280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020746f3a20746f2e62797465732c0a20202020202020202020202020202020646174613a20646174612c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020292061732120526573756c740a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a202020202020202029207b0a20202020202020202020202045564d2e626f72726f774272696467654163636573736f7228292e6465706f7369744e4654286e66743a203c2d6e66742c20746f3a2073656c662e6164647265737328292c2066656550726f76696465723a2066656550726f7669646572290a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a2020202020202020616363657373284f776e6572207c20427269646765290a202020202020202066756e2077697468647261774e4654280a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a20202020202020202020202072657475726e203c2d2045564d2e626f72726f774272696467654163636573736f7228292e77697468647261774e4654280a2020202020202020202020202020202063616c6c65723a202673656c6620617320617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a20202020202020202020202020202020747970653a20747970652c0a2020202020202020202020202020202069643a2069642c0a2020202020202020202020202020202066656550726f76696465723a2066656550726f76696465720a202020202020202020202020290a20202020202020207d0a202020207d0a0a202020202f2f2f20437265617465732061206e657720636164656e6365206f776e6564206163636f756e740a2020202061636365737328616c6c290a2020202066756e20637265617465436164656e63654f776e65644163636f756e7428293a2040436164656e63654f776e65644163636f756e74207b0a20202020202020206c657420616363203c2d63726561746520436164656e63654f776e65644163636f756e7428290a20202020202020206c65742061646472203d20496e7465726e616c45564d2e637265617465436164656e63654f776e65644163636f756e7428757569643a206163632e75756964290a20202020202020206163632e696e697441646472657373286164647265737342797465733a2061646472290a2020202020202020656d697420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a2061646472290a202020202020202072657475726e203c2d6163630a202020207d0a0a202020202f2f2f2052756e7320616e206120524c502d656e636f6465642045564d207472616e73616374696f6e2c2064656475637473207468652067617320666565732c0a202020202f2f2f20616e64206465706f736974732074686520676173206665657320696e746f207468652070726f766964656420636f696e6261736520616464726573732e0a2020202061636365737328616c6c290a2020202066756e2072756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a202020202020202072657475726e20496e7465726e616c45564d2e72756e280a2020202020202020202020202020202074783a2074782c0a20202020202020202020202020202020636f696e626173653a20636f696e626173652e62797465730a2020202020202020292061732120526573756c740a202020207d0a0a202020202f2f2f206d75737452756e2072756e7320746865207472616e73616374696f6e207573696e672045564d2e72756e207965742069740a202020202f2f2f20726f6c6c6261636b2069662074686520747820657865637574696f6e2073746174757320697320756e6b6e6f776e206f7220696e76616c69642e0a202020202f2f2f204e6f746520746861742074686973206d6574686f6420646f6573206e6f7420726f6c6c6261636b206966207472616e73616374696f6e0a202020202f2f2f2069732065786563757465642062757420616e20766d206572726f72206973207265706f7274656420617320746865206f7574636f6d650a202020202f2f2f206f662074686520657865637574696f6e20287374617475733a206661696c6564292e0a2020202061636365737328616c6c290a2020202066756e206d75737452756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a20202020202020206c65742072756e526573756c74203d2073656c662e72756e2874783a2074782c20636f696e626173653a20636f696e62617365290a2020202020202020617373657274280a20202020202020202020202072756e526573756c742e737461747573203d3d205374617475732e6661696c6564207c7c2072756e526573756c742e737461747573203d3d205374617475732e7375636365737366756c2c0a2020202020202020202020206d6573736167653a20227478206973206e6f742076616c696420666f7220657865637574696f6e220a2020202020202020290a202020202020202072657475726e2072756e526573756c740a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249285f2076616c7565733a205b416e795374727563745d293a205b55496e74385d207b0a202020202020202072657475726e20496e7465726e616c45564d2e656e636f64654142492876616c756573290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f64654142492874797065733a205b547970655d2c20646174613a205b55496e74385d293a205b416e795374727563745d207b0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a20202020202020205f2076616c7565733a205b416e795374727563745d0a20202020293a205b55496e74385d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a20202020202020206c657420617267756d656e7473203d20496e7465726e616c45564d2e656e636f64654142492876616c756573290a0a202020202020202072657475726e206d6574686f6449442e636f6e63617428617267756d656e7473290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a202020202020202074797065733a205b547970655d2c0a2020202020202020646174613a205b55496e74385d0a20202020293a205b416e795374727563745d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a0a2020202020202020666f72206279746520696e206d6574686f644944207b0a2020202020202020202020206966206279746520213d20646174612e72656d6f766546697273742829207b0a2020202020202020202020202020202070616e696328227369676e6174757265206d69736d6174636822290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a202020202f2f2f2056616c69646174696f6e526573756c742072657475726e732074686520726573756c74206f6620434f41206f776e6572736869702070726f6f662076616c69646174696f6e0a2020202061636365737328616c6c290a202020207374727563742056616c69646174696f6e526573756c74207b0a202020202020202061636365737328616c6c290a20202020202020206c657420697356616c69643a20426f6f6c0a0a202020202020202061636365737328616c6c290a20202020202020206c65742070726f626c656d3a20537472696e673f0a0a2020202020202020696e697428697356616c69643a20426f6f6c2c2070726f626c656d3a20537472696e673f29207b0a20202020202020202020202073656c662e697356616c6964203d20697356616c69640a20202020202020202020202073656c662e70726f626c656d203d2070726f626c656d0a20202020202020207d0a202020207d0a0a202020202f2f2f2076616c6964617465434f414f776e65727368697050726f6f662076616c696461746573206120434f41206f776e6572736869702070726f6f660a2020202061636365737328616c6c290a2020202066756e2076616c6964617465434f414f776e65727368697050726f6f66280a2020202020202020616464726573733a20416464726573732c0a2020202020202020706174683a205075626c6963506174682c0a20202020202020207369676e6564446174613a205b55496e74385d2c0a20202020202020206b6579496e64696365733a205b55496e7436345d2c0a20202020202020207369676e6174757265733a205b5b55496e74385d5d2c0a202020202020202065766d416464726573733a205b55496e74383b2032305d0a20202020293a2056616c69646174696f6e526573756c74207b0a0a20202020202020202f2f206d616b65207369676e6174757265207365742066697273740a20202020202020202f2f20636865636b206e756d626572206f66207369676e617475726573206d617463686573206e756d626572206f66206b657920696e64696365730a20202020202020206966206b6579496e64696365732e6c656e67746820213d207369676e6174757265732e6c656e677468207b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a20226b657920696e64696365732073697a6520646f65736e2774206d6174636820746865207369676e617475726573220a202020202020202020202020290a20202020202020207d0a0a2020202020202020766172207369676e61747572655365743a205b43727970746f2e4b65794c6973745369676e61747572655d203d205b5d0a2020202020202020666f72207369676e6174757265496e6465782c207369676e617475726520696e207369676e6174757265737b0a2020202020202020202020207369676e61747572655365742e617070656e642843727970746f2e4b65794c6973745369676e6174757265280a202020202020202020202020202020206b6579496e6465783a20496e74286b6579496e64696365735b7369676e6174757265496e6465785d292c0a202020202020202020202020202020207369676e61747572653a207369676e61747572650a20202020202020202020202029290a20202020202020207d0a0a20202020202020202f2f206665746368206163636f756e740a20202020202020206c657420616363203d206765744163636f756e742861646472657373290a0a20202020202020202f2f20636f6e737472756374696e67206b6579206c6973740a20202020202020206c6574206b65794c697374203d2043727970746f2e4b65794c69737428290a2020202020202020666f72207369676e617475726520696e207369676e6174757265536574207b0a2020202020202020202020206c6574206b6579203d206163632e6b6579732e676574286b6579496e6465783a207369676e61747572652e6b6579496e64657829210a20202020202020202020202061737365727428216b65792e69735265766f6b65642c206d6573736167653a20227265766f6b6564206b6579206973207573656422290a2020202020202020202020206b65794c6973742e616464280a20202020202020202020202020206b65792e7075626c69634b65792c0a202020202020202020202020202068617368416c676f726974686d3a206b65792e68617368416c676f726974686d2c0a20202020202020202020202020207765696768743a206b65792e7765696768742c0a2020202020202020202020290a20202020202020207d0a0a20202020202020206c657420697356616c6964203d206b65794c6973742e766572696679280a2020202020202020202020207369676e61747572655365743a207369676e61747572655365742c0a2020202020202020202020207369676e6564446174613a207369676e6564446174612c0a202020202020202020202020646f6d61696e53657061726174696f6e5461673a2022464c4f572d56302e302d75736572220a2020202020202020290a0a202020202020202069662021697356616c69647b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a202274686520676976656e207369676e61747572657320617265206e6f742076616c6964206f722070726f7669646520656e6f75676820776569676874220a202020202020202020202020290a20202020202020207d0a0a20202020202020206c657420636f61526566203d206163632e6361706162696c69746965732e626f72726f773c2645564d2e436164656e63654f776e65644163636f756e743e2870617468290a0a2020202020202020696620636f61526566203d3d206e696c207b0a2020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202070726f626c656d3a2022636f756c64206e6f7420626f72726f7720627269646765206163636f756e742773207265736f75726365220a20202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f207665726966792065766d2061646472657373206d61746368696e670a20202020202020207661722061646472203d20636f61526566212e6164647265737328290a2020202020202020666f7220696e6465782c206974656d20696e20636f61526566212e6164647265737328292e6279746573207b0a2020202020202020202020206966206974656d20213d2065766d416464726573735b696e6465785d207b0a2020202020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202020202070726f626c656d3a202265766d2061646472657373206d69736d61746368220a20202020202020202020202020202020290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e2056616c69646174696f6e526573756c74280a202020202020202020202020697356616c69643a20747275652c0a20202020202020202020202070726f626c656d3a206e696c0a2020202020202020290a202020207d0a0a202020202f2f2f2052657475726e732061207265666572656e636520746f20746865204272696467654163636573736f722064657369676e6174656420666f7220696e7465726e616c206272696467652072657175657374730a202020206163636573732873656c66290a20202020766965772066756e20626f72726f774272696467654163636573736f7228293a2061757468284272696467652920267b4272696467654163636573736f727d207b0a202020202020202072657475726e2073656c662e6163636f756e742e73746f726167652e626f72726f773c61757468284272696467652920267b4272696467654163636573736f727d3e2866726f6d3a202f73746f726167652f65766d427269646765526f75746572290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f77207265666572656e636520746f207468652045564d2062726964676522290a202020207d0a0a202020202f2f2f20496e7465726661636520666f722061207265736f75726365207768696368206163747320617320616e20656e747279706f696e7420746f2074686520564d206272696467650a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204272696467654163636573736f72207b0a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e465420746f2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a202020202020202020202020746f3a2045564d2e45564d416464726573732c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020290a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e46542066726f6d2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e2077697468647261774e4654280a20202020202020202020202063616c6c65723a20617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d0a202020207d0a7d0a" + +access(all) +fun setup() { + var err = Test.deployContract( + name: "ViewResolver", + path: "../contracts/standards/ViewResolver.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "Burner", + path: "../contracts/standards/Burner.cdc", + arguments: [] + ) + err = Test.deployContract( + name: "FungibleToken", + path: "../contracts/standards/FungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "NonFungibleToken", + path: "../contracts/standards/NonFungibleToken.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "MetadataViews", + path: "../contracts/standards/MetadataViews.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FungibleTokenMetadataViews", + path: "../contracts/standards/FungibleTokenMetadataViews.cdc", + arguments: [] + ) + let updateEVMResult = executeTransaction( + "../transactions/test/update_contract.cdc", + ["EVM", updatedEVMCodeHex], + serviceAccount + ) + Test.expect(updateEVMResult, Test.beSucceeded()) +} + +access(all) +fun testCreateCOASucceeds() { + let transferFlowResult = executeTransaction( + "../transactions/flow-token/transfer_flow.cdc", + [alice.address, 1000.0], + serviceAccount + ) + Test.expect(transferFlowResult, Test.beSucceeded()) + + + // let createCOAResult = executeTransaction( + // "../transactions/evm/create_account.cdc", + // [1000.0], + // alice + // ) + // Test.expect(createCOAResult, Test.beSucceeded()) + + // let coaAddressResult = executeScript( + // "../scripts/evm/get_evm_address_string.cdc", + // [alice.address] + // ) + // Test.expect(coaAddressResult, Test.beSucceeded()) +} From 1e601e616f6fdcf7388e62f9deb429c32c1dd240 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 20 Mar 2024 18:28:08 +0200 Subject: [PATCH 27/39] Fix testing aliases in flow.json config file and update tests --- cadence/tests/flow_evm_bridge_tests.cdc | 71 +++++-------------------- flow.json | 8 +-- 2 files changed, 14 insertions(+), 65 deletions(-) diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index c9095273..36e45567 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -4,52 +4,6 @@ import BlockchainHelpers access(all) let serviceAccount = Test.serviceAccount() access(all) let alice = Test.createAccount() -access(all) let updatedEVMCodeHex = "696d706f72742043727970746f0a696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a61636365737328616c6c290a636f6e74726163742045564d207b0a0a202020202f2f20456e7469746c656d656e747320656e61626c696e672066696e65722d6772616e65642061636365737320636f6e74726f6c206f6e206120436164656e63654f776e65644163636f756e740a2020202061636365737328616c6c2920656e7469746c656d656e742056616c69646174650a2020202061636365737328616c6c2920656e7469746c656d656e742057697468647261770a2020202061636365737328616c6c2920656e7469746c656d656e742043616c6c0a2020202061636365737328616c6c2920656e7469746c656d656e74204465706c6f790a2020202061636365737328616c6c2920656e7469746c656d656e74204f776e65720a2020202061636365737328616c6c2920656e7469746c656d656e74204272696467650a0a2020202061636365737328616c6c290a202020206576656e7420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a205b55496e74383b2032305d290a0a202020202f2f2f2045564d4164647265737320697320616e2045564d2d636f6d70617469626c6520616464726573730a2020202061636365737328616c6c290a202020207374727563742045564d41646472657373207b0a0a20202020202020202f2f2f204279746573206f662074686520616464726573730a202020202020202061636365737328616c6c290a20202020202020206c65742062797465733a205b55496e74383b2032305d0a0a20202020202020202f2f2f20436f6e737472756374732061206e65772045564d20616464726573732066726f6d2074686520676976656e206279746520726570726573656e746174696f6e0a20202020202020207669657720696e69742862797465733a205b55496e74383b2032305d29207b0a20202020202020202020202073656c662e6279746573203d2062797465730a20202020202020207d0a0a20202020202020202f2f2f2042616c616e6365206f662074686520616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a2020202020202020202020206c65742062616c616e6365203d20496e7465726e616c45564d2e62616c616e6365280a20202020202020202020202020202020616464726573733a2073656c662e62797465730a202020202020202020202020290a20202020202020202020202072657475726e2042616c616e6365286174746f666c6f773a2062616c616e6365290a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207374727563742042616c616e6365207b0a0a20202020202020202f2f2f205468652062616c616e636520696e206174746f2d464c4f570a20202020202020202f2f2f204174746f2d464c4f572069732074686520736d616c6c6573742064656e6f6d696e6174696f6e206f6620464c4f5720283165313820464c4f57290a20202020202020202f2f2f2074686174206973207573656420746f2073746f7265206163636f756e742062616c616e63657320696e736964652045564d0a20202020202020202f2f2f2073696d696c617220746f207468652077617920574549206973207573656420746f2073746f72652045544820646976697369626c6520746f20313820646563696d616c20706c616365732e0a202020202020202061636365737328616c6c290a2020202020202020766172206174746f666c6f773a2055496e740a0a20202020202020202f2f2f20436f6e737472756374732061206e65772062616c616e63650a202020202020202061636365737328616c6c290a20202020202020207669657720696e6974286174746f666c6f773a2055496e7429207b0a20202020202020202020202073656c662e6174746f666c6f77203d206174746f666c6f770a20202020202020207d0a0a20202020202020202f2f2f2053657473207468652062616c616e636520627920612055466978363420283820646563696d616c20706f696e7473292c2074686520666f726d61740a20202020202020202f2f2f2074686174206973207573656420696e20436164656e636520746f2073746f726520464c4f5720746f6b656e732e0a202020202020202061636365737328616c6c290a202020202020202066756e20736574464c4f5728666c6f773a20554669783634297b0a20202020202020202020202073656c662e6174746f666c6f77203d20496e7465726e616c45564d2e63617374546f4174746f464c4f572862616c616e63653a20666c6f77290a20202020202020207d0a0a20202020202020202f2f2f204361737473207468652062616c616e636520746f2061205546697836342028726f756e64696e6720646f776e290a20202020202020202f2f2f205761726e696e67212063617374696e6720612062616c616e636520746f20612055466978363420776869636820737570706f7274732061206c6f776572206c6576656c206f6620707265636973696f6e0a20202020202020202f2f2f20283820646563696d616c20706f696e747320696e20636f6d7061726520746f20313829206d6967687420726573756c7420696e20726f756e64696e6720646f776e206572726f722e0a20202020202020202f2f2f205573652074686520746f4174746f466c6f772066756e6374696f6e20696620796f752063617265206e656564206d6f72652061636375726163792e0a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e464c4f5728293a20554669783634207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63617374546f464c4f572862616c616e63653a2073656c662e6174746f666c6f77290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e73207468652062616c616e636520696e204174746f2d464c4f570a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e4174746f464c4f5728293a2055496e74207b0a20202020202020202020202072657475726e2073656c662e6174746f666c6f770a20202020202020207d0a202020207d0a0a202020202f2f2f207265706f7274732074686520737461747573206f662065766d20657865637574696f6e2e0a2020202061636365737328616c6c2920656e756d205374617475733a2055496e7438207b0a20202020202020202f2f2f2069732028726172656c79292072657475726e6564207768656e2073746174757320697320756e6b6e6f776e0a20202020202020202f2f2f20616e6420736f6d657468696e672068617320676f6e6520766572792077726f6e672e0a202020202020202061636365737328616c6c29206361736520756e6b6e6f776e0a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206661696c6564206174207468652076616c69646174696f6e20737465702028652e672e206e6f6e6365206d69736d61746368292e0a20202020202020202f2f2f20416e20696e76616c6964207472616e73616374696f6e2f63616c6c2069732072656a656374656420746f2062652065786563757465640a20202020202020202f2f2f206f7220626520696e636c7564656420696e206120626c6f636b2e0a202020202020202061636365737328616c6c29206361736520696e76616c69640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c206275742074686520766d20686173207265706f7274656420616e206572726f722061730a20202020202020202f2f2f20746865206f7574636f6d65206f6620657865637574696f6e2028652e672e2072756e6e696e67206f7574206f6620676173292e0a20202020202020202f2f2f2041206661696c65642074782f63616c6c20697320696e636c7564656420696e206120626c6f636b2e0a20202020202020202f2f2f204e6f746520746861742072657375626d697373696f6e206f662061206661696c6564207472616e73616374696f6e20776f756c640a20202020202020202f2f2f20726573756c7420696e20696e76616c69642073746174757320696e20746865207365636f6e6420617474656d70742c20676976656e0a20202020202020202f2f2f20746865206e6f6e636520776f756c6420626520636f6d6520696e76616c69642e0a202020202020202061636365737328616c6c292063617365206661696c65640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c20616e64206e6f206572726f72206973207265706f727465642062792074686520766d2e0a202020202020202061636365737328616c6c292063617365207375636365737366756c0a202020207d0a0a202020202f2f2f207265706f72747320746865206f7574636f6d65206f662065766d207472616e73616374696f6e2f63616c6c20657865637574696f6e20617474656d70740a2020202061636365737328616c6c292073747275637420526573756c74207b0a20202020202020202f2f2f20737461747573206f662074686520657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c6574207374617475733a205374617475730a0a20202020202020202f2f2f206572726f7220636f646520286572726f7220636f6465207a65726f206d65616e73206e6f206572726f72290a202020202020202061636365737328616c6c290a20202020202020206c6574206572726f72436f64653a2055496e7436340a0a20202020202020202f2f2f2072657475726e732074686520616d6f756e74206f6620676173206d65746572656420647572696e670a20202020202020202f2f2f2065766d20657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c657420676173557365643a2055496e7436340a0a20202020202020202f2f2f2072657475726e7320746865206461746120746861742069732072657475726e65642066726f6d0a20202020202020202f2f2f207468652065766d20666f72207468652063616c6c2e20466f7220636f612e6465706c6f790a20202020202020202f2f2f2063616c6c732069742072657475726e73207468652061646472657373206279746573206f66207468650a20202020202020202f2f2f206e65776c79206465706c6f79656420636f6e74726163742e0a202020202020202061636365737328616c6c290a20202020202020206c657420646174613a205b55496e74385d0a0a2020202020202020696e6974280a2020202020202020202020207374617475733a205374617475732c0a2020202020202020202020206572726f72436f64653a2055496e7436342c0a202020202020202020202020676173557365643a2055496e7436342c0a202020202020202020202020646174613a205b55496e74385d0a202020202020202029207b0a20202020202020202020202073656c662e737461747573203d207374617475730a20202020202020202020202073656c662e6572726f72436f6465203d206572726f72436f64650a20202020202020202020202073656c662e67617355736564203d20676173557365640a20202020202020202020202073656c662e64617461203d20646174610a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204164647265737361626c65207b0a20202020202020202f2f2f205468652045564d20616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d416464726573730a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520436164656e63654f776e65644163636f756e743a204164647265737361626c65207b0a0a20202020202020206163636573732873656c66290a2020202020202020766172206164647265737342797465733a205b55496e74383b2032305d0a0a2020202020202020696e69742829207b0a2020202020202020202020202f2f206164647265737320697320696e697469616c6c792073657420746f207a65726f0a2020202020202020202020202f2f206275742075706461746564207468726f75676820696e697441646472657373206c617465720a2020202020202020202020202f2f207765206861766520746f20646f20746869732073696e6365207765206e656564207265736f75726365206964202875756964290a2020202020202020202020202f2f20746f2063616c63756c617465207468652045564d206164647265737320666f72207468697320636164656e6365206f776e6564206163636f756e740a20202020202020202020202073656c662e616464726573734279746573203d205b302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20305d0a20202020202020207d0a0a202020202020202061636365737328636f6e7472616374290a202020202020202066756e20696e697441646472657373286164647265737342797465733a205b55496e74383b2032305d29207b0a20202020202020202020202f2f206f6e6c7920616c6c6f7720736574206164647265737320666f72207468652066697273742074696d650a20202020202020202020202f2f20636865636b206164647265737320697320656d7074790a202020202020202020202020666f72206974656d20696e2073656c662e616464726573734279746573207b0a20202020202020202020202020202020617373657274286974656d203d3d20302c206d6573736167653a2022616464726573732062797465206973206e6f7420656d70747922290a2020202020202020202020207d0a202020202020202020202073656c662e616464726573734279746573203d206164647265737342797465730a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d41646472657373207b0a2020202020202020202020202f2f20416c77617973206372656174652061206e65772045564d4164647265737320696e7374616e63650a20202020202020202020202072657475726e2045564d416464726573732862797465733a2073656c662e616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f204765742062616c616e6365206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a20202020202020202020202072657475726e2073656c662e6164647265737328292e62616c616e636528290a20202020202020207d0a0a20202020202020202f2f2f204465706f736974732074686520676976656e207661756c7420696e746f2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369742866726f6d3a2040466c6f77546f6b656e2e5661756c7429207b0a202020202020202020202020496e7465726e616c45564d2e6465706f736974280a2020202020202020202020202020202066726f6d3a203c2d66726f6d2c0a20202020202020202020202020202020746f3a2073656c662e6164647265737342797465730a202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e7420626568696e6420616e20656e7469746c656d656e742c20616374696e672061732070726f6f66206f66206163636573730a2020202020202020616363657373284f776e6572207c2056616c6964617465290a2020202020202020766965772066756e2070726f7465637465644164647265737328293a2045564d41646472657373207b0a20202020202020202020202072657475726e2073656c662e6164647265737328290a20202020202020207d0a0a20202020202020202f2f2f20576974686472617773207468652062616c616e63652066726f6d2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a20202020202020202f2f2f204e6f7465207468617420616d6f756e747320736d616c6c6572207468616e2031306e4620283130652d38292063616e27742062652077697468647261776e0a20202020202020202f2f2f20676976656e207468617420466c6f7720546f6b656e205661756c747320757365205546697836347320746f2073746f72652062616c616e6365732e0a20202020202020202f2f2f2049662074686520676976656e2062616c616e636520636f6e76657273696f6e20746f2055466978363420726573756c747320696e0a20202020202020202f2f2f20726f756e64696e67206572726f722c20746869732066756e6374696f6e20776f756c64206661696c2e0a2020202020202020616363657373284f776e6572207c205769746864726177290a202020202020202066756e2077697468647261772862616c616e63653a2042616c616e6365293a2040466c6f77546f6b656e2e5661756c74207b0a2020202020202020202020206c6574207661756c74203c2d20496e7465726e616c45564d2e7769746864726177280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020616d6f756e743a2062616c616e63652e6174746f666c6f770a20202020202020202020202029206173212040466c6f77546f6b656e2e5661756c740a20202020202020202020202072657475726e203c2d7661756c740a20202020202020207d0a0a20202020202020202f2f2f204465706c6f7973206120636f6e747261637420746f207468652045564d20656e7669726f6e6d656e742e0a20202020202020202f2f2f2052657475726e73207468652061646472657373206f6620746865206e65776c79206465706c6f79656420636f6e74726163740a2020202020202020616363657373284f776e6572207c204465706c6f79290a202020202020202066756e206465706c6f79280a202020202020202020202020636f64653a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a2045564d41646472657373207b0a2020202020202020202020206c657420616464726573734279746573203d20496e7465726e616c45564d2e6465706c6f79280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020636f64653a20636f64652c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020290a20202020202020202020202072657475726e2045564d416464726573732862797465733a20616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f2043616c6c7320612066756e6374696f6e20776974682074686520676976656e20646174612e0a20202020202020202f2f2f2054686520657865637574696f6e206973206c696d697465642062792074686520676976656e20616d6f756e74206f66206761730a2020202020202020616363657373284f776e6572207c2043616c6c290a202020202020202066756e2063616c6c280a202020202020202020202020746f3a2045564d416464726573732c0a202020202020202020202020646174613a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a20526573756c74207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63616c6c280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020746f3a20746f2e62797465732c0a20202020202020202020202020202020646174613a20646174612c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020292061732120526573756c740a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a202020202020202029207b0a20202020202020202020202045564d2e626f72726f774272696467654163636573736f7228292e6465706f7369744e4654286e66743a203c2d6e66742c20746f3a2073656c662e6164647265737328292c2066656550726f76696465723a2066656550726f7669646572290a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a2020202020202020616363657373284f776e6572207c20427269646765290a202020202020202066756e2077697468647261774e4654280a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a20202020202020202020202072657475726e203c2d2045564d2e626f72726f774272696467654163636573736f7228292e77697468647261774e4654280a2020202020202020202020202020202063616c6c65723a202673656c6620617320617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a20202020202020202020202020202020747970653a20747970652c0a2020202020202020202020202020202069643a2069642c0a2020202020202020202020202020202066656550726f76696465723a2066656550726f76696465720a202020202020202020202020290a20202020202020207d0a202020207d0a0a202020202f2f2f20437265617465732061206e657720636164656e6365206f776e6564206163636f756e740a2020202061636365737328616c6c290a2020202066756e20637265617465436164656e63654f776e65644163636f756e7428293a2040436164656e63654f776e65644163636f756e74207b0a20202020202020206c657420616363203c2d63726561746520436164656e63654f776e65644163636f756e7428290a20202020202020206c65742061646472203d20496e7465726e616c45564d2e637265617465436164656e63654f776e65644163636f756e7428757569643a206163632e75756964290a20202020202020206163632e696e697441646472657373286164647265737342797465733a2061646472290a2020202020202020656d697420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a2061646472290a202020202020202072657475726e203c2d6163630a202020207d0a0a202020202f2f2f2052756e7320616e206120524c502d656e636f6465642045564d207472616e73616374696f6e2c2064656475637473207468652067617320666565732c0a202020202f2f2f20616e64206465706f736974732074686520676173206665657320696e746f207468652070726f766964656420636f696e6261736520616464726573732e0a2020202061636365737328616c6c290a2020202066756e2072756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a202020202020202072657475726e20496e7465726e616c45564d2e72756e280a2020202020202020202020202020202074783a2074782c0a20202020202020202020202020202020636f696e626173653a20636f696e626173652e62797465730a2020202020202020292061732120526573756c740a202020207d0a0a202020202f2f2f206d75737452756e2072756e7320746865207472616e73616374696f6e207573696e672045564d2e72756e207965742069740a202020202f2f2f20726f6c6c6261636b2069662074686520747820657865637574696f6e2073746174757320697320756e6b6e6f776e206f7220696e76616c69642e0a202020202f2f2f204e6f746520746861742074686973206d6574686f6420646f6573206e6f7420726f6c6c6261636b206966207472616e73616374696f6e0a202020202f2f2f2069732065786563757465642062757420616e20766d206572726f72206973207265706f7274656420617320746865206f7574636f6d650a202020202f2f2f206f662074686520657865637574696f6e20287374617475733a206661696c6564292e0a2020202061636365737328616c6c290a2020202066756e206d75737452756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a20202020202020206c65742072756e526573756c74203d2073656c662e72756e2874783a2074782c20636f696e626173653a20636f696e62617365290a2020202020202020617373657274280a20202020202020202020202072756e526573756c742e737461747573203d3d205374617475732e6661696c6564207c7c2072756e526573756c742e737461747573203d3d205374617475732e7375636365737366756c2c0a2020202020202020202020206d6573736167653a20227478206973206e6f742076616c696420666f7220657865637574696f6e220a2020202020202020290a202020202020202072657475726e2072756e526573756c740a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249285f2076616c7565733a205b416e795374727563745d293a205b55496e74385d207b0a202020202020202072657475726e20496e7465726e616c45564d2e656e636f64654142492876616c756573290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f64654142492874797065733a205b547970655d2c20646174613a205b55496e74385d293a205b416e795374727563745d207b0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a20202020202020205f2076616c7565733a205b416e795374727563745d0a20202020293a205b55496e74385d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a20202020202020206c657420617267756d656e7473203d20496e7465726e616c45564d2e656e636f64654142492876616c756573290a0a202020202020202072657475726e206d6574686f6449442e636f6e63617428617267756d656e7473290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a202020202020202074797065733a205b547970655d2c0a2020202020202020646174613a205b55496e74385d0a20202020293a205b416e795374727563745d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a0a2020202020202020666f72206279746520696e206d6574686f644944207b0a2020202020202020202020206966206279746520213d20646174612e72656d6f766546697273742829207b0a2020202020202020202020202020202070616e696328227369676e6174757265206d69736d6174636822290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a202020202f2f2f2056616c69646174696f6e526573756c742072657475726e732074686520726573756c74206f6620434f41206f776e6572736869702070726f6f662076616c69646174696f6e0a2020202061636365737328616c6c290a202020207374727563742056616c69646174696f6e526573756c74207b0a202020202020202061636365737328616c6c290a20202020202020206c657420697356616c69643a20426f6f6c0a0a202020202020202061636365737328616c6c290a20202020202020206c65742070726f626c656d3a20537472696e673f0a0a2020202020202020696e697428697356616c69643a20426f6f6c2c2070726f626c656d3a20537472696e673f29207b0a20202020202020202020202073656c662e697356616c6964203d20697356616c69640a20202020202020202020202073656c662e70726f626c656d203d2070726f626c656d0a20202020202020207d0a202020207d0a0a202020202f2f2f2076616c6964617465434f414f776e65727368697050726f6f662076616c696461746573206120434f41206f776e6572736869702070726f6f660a2020202061636365737328616c6c290a2020202066756e2076616c6964617465434f414f776e65727368697050726f6f66280a2020202020202020616464726573733a20416464726573732c0a2020202020202020706174683a205075626c6963506174682c0a20202020202020207369676e6564446174613a205b55496e74385d2c0a20202020202020206b6579496e64696365733a205b55496e7436345d2c0a20202020202020207369676e6174757265733a205b5b55496e74385d5d2c0a202020202020202065766d416464726573733a205b55496e74383b2032305d0a20202020293a2056616c69646174696f6e526573756c74207b0a0a20202020202020202f2f206d616b65207369676e6174757265207365742066697273740a20202020202020202f2f20636865636b206e756d626572206f66207369676e617475726573206d617463686573206e756d626572206f66206b657920696e64696365730a20202020202020206966206b6579496e64696365732e6c656e67746820213d207369676e6174757265732e6c656e677468207b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a20226b657920696e64696365732073697a6520646f65736e2774206d6174636820746865207369676e617475726573220a202020202020202020202020290a20202020202020207d0a0a2020202020202020766172207369676e61747572655365743a205b43727970746f2e4b65794c6973745369676e61747572655d203d205b5d0a2020202020202020666f72207369676e6174757265496e6465782c207369676e617475726520696e207369676e6174757265737b0a2020202020202020202020207369676e61747572655365742e617070656e642843727970746f2e4b65794c6973745369676e6174757265280a202020202020202020202020202020206b6579496e6465783a20496e74286b6579496e64696365735b7369676e6174757265496e6465785d292c0a202020202020202020202020202020207369676e61747572653a207369676e61747572650a20202020202020202020202029290a20202020202020207d0a0a20202020202020202f2f206665746368206163636f756e740a20202020202020206c657420616363203d206765744163636f756e742861646472657373290a0a20202020202020202f2f20636f6e737472756374696e67206b6579206c6973740a20202020202020206c6574206b65794c697374203d2043727970746f2e4b65794c69737428290a2020202020202020666f72207369676e617475726520696e207369676e6174757265536574207b0a2020202020202020202020206c6574206b6579203d206163632e6b6579732e676574286b6579496e6465783a207369676e61747572652e6b6579496e64657829210a20202020202020202020202061737365727428216b65792e69735265766f6b65642c206d6573736167653a20227265766f6b6564206b6579206973207573656422290a2020202020202020202020206b65794c6973742e616464280a20202020202020202020202020206b65792e7075626c69634b65792c0a202020202020202020202020202068617368416c676f726974686d3a206b65792e68617368416c676f726974686d2c0a20202020202020202020202020207765696768743a206b65792e7765696768742c0a2020202020202020202020290a20202020202020207d0a0a20202020202020206c657420697356616c6964203d206b65794c6973742e766572696679280a2020202020202020202020207369676e61747572655365743a207369676e61747572655365742c0a2020202020202020202020207369676e6564446174613a207369676e6564446174612c0a202020202020202020202020646f6d61696e53657061726174696f6e5461673a2022464c4f572d56302e302d75736572220a2020202020202020290a0a202020202020202069662021697356616c69647b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a202274686520676976656e207369676e61747572657320617265206e6f742076616c6964206f722070726f7669646520656e6f75676820776569676874220a202020202020202020202020290a20202020202020207d0a0a20202020202020206c657420636f61526566203d206163632e6361706162696c69746965732e626f72726f773c2645564d2e436164656e63654f776e65644163636f756e743e2870617468290a0a2020202020202020696620636f61526566203d3d206e696c207b0a2020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202070726f626c656d3a2022636f756c64206e6f7420626f72726f7720627269646765206163636f756e742773207265736f75726365220a20202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f207665726966792065766d2061646472657373206d61746368696e670a20202020202020207661722061646472203d20636f61526566212e6164647265737328290a2020202020202020666f7220696e6465782c206974656d20696e20636f61526566212e6164647265737328292e6279746573207b0a2020202020202020202020206966206974656d20213d2065766d416464726573735b696e6465785d207b0a2020202020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202020202070726f626c656d3a202265766d2061646472657373206d69736d61746368220a20202020202020202020202020202020290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e2056616c69646174696f6e526573756c74280a202020202020202020202020697356616c69643a20747275652c0a20202020202020202020202070726f626c656d3a206e696c0a2020202020202020290a202020207d0a0a202020202f2f2f2052657475726e732061207265666572656e636520746f20746865204272696467654163636573736f722064657369676e6174656420666f7220696e7465726e616c206272696467652072657175657374730a202020206163636573732873656c66290a20202020766965772066756e20626f72726f774272696467654163636573736f7228293a2061757468284272696467652920267b4272696467654163636573736f727d207b0a202020202020202072657475726e2073656c662e6163636f756e742e73746f726167652e626f72726f773c61757468284272696467652920267b4272696467654163636573736f727d3e2866726f6d3a202f73746f726167652f65766d427269646765526f75746572290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f77207265666572656e636520746f207468652045564d2062726964676522290a202020207d0a0a202020202f2f2f20496e7465726661636520666f722061207265736f75726365207768696368206163747320617320616e20656e747279706f696e7420746f2074686520564d206272696467650a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204272696467654163636573736f72207b0a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e465420746f2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a202020202020202020202020746f3a2045564d2e45564d416464726573732c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020290a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e46542066726f6d2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e2077697468647261774e4654280a20202020202020202020202063616c6c65723a20617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d0a202020207d0a7d0a" - -access(all) -fun setup() { - var err = Test.deployContract( - name: "ViewResolver", - path: "../contracts/standards/ViewResolver.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "Burner", - path: "../contracts/standards/Burner.cdc", - arguments: [] - ) - err = Test.deployContract( - name: "FungibleToken", - path: "../contracts/standards/FungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "NonFungibleToken", - path: "../contracts/standards/NonFungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "MetadataViews", - path: "../contracts/standards/MetadataViews.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "FungibleTokenMetadataViews", - path: "../contracts/standards/FungibleTokenMetadataViews.cdc", - arguments: [] - ) - let updateEVMResult = executeTransaction( - "../transactions/test/update_contract.cdc", - ["EVM", updatedEVMCodeHex], - serviceAccount - ) - Test.expect(updateEVMResult, Test.beSucceeded()) -} - access(all) fun testCreateCOASucceeds() { let transferFlowResult = executeTransaction( @@ -59,17 +13,18 @@ fun testCreateCOASucceeds() { ) Test.expect(transferFlowResult, Test.beSucceeded()) + let createCOAResult = executeTransaction( + "../transactions/evm/create_account.cdc", + [1000.0], + alice + ) + Test.expect(createCOAResult, Test.beSucceeded()) - // let createCOAResult = executeTransaction( - // "../transactions/evm/create_account.cdc", - // [1000.0], - // alice - // ) - // Test.expect(createCOAResult, Test.beSucceeded()) - - // let coaAddressResult = executeScript( - // "../scripts/evm/get_evm_address_string.cdc", - // [alice.address] - // ) - // Test.expect(coaAddressResult, Test.beSucceeded()) + let coaAddressResult = executeScript( + "../scripts/evm/get_evm_address_string.cdc", + [alice.address] + ) + Test.expect(coaAddressResult, Test.beSucceeded()) + let stringAddress = coaAddressResult.returnValue as! String? + Test.assertEqual(40, stringAddress!.length) } diff --git a/flow.json b/flow.json index 0b48e44a..d16493e3 100644 --- a/flow.json +++ b/flow.json @@ -16,8 +16,7 @@ "source": "./cadence/contracts/standards/Burner.cdc", "aliases": { "emulator": "ee82856bf20e2aa6", - "previewnet": "b6763b4399a888c8", - "testing": "0000000000000007" + "previewnet": "b6763b4399a888c8" } }, "CrossVMNFT": { @@ -91,7 +90,6 @@ "emulator": "ee82856bf20e2aa6", "mainnet": "f233dcee88fe0abe", "previewnet": "a0225e7000ac82a9", - "testing": "0000000000000007", "testnet": "9a0766d93b6608b7" } }, @@ -101,7 +99,6 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "f233dcee88fe0abe", "previewnet": "a0225e7000ac82a9", - "testing": "0000000000000007", "testnet": "9a0766d93b6608b7" } }, @@ -129,7 +126,6 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", - "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } }, @@ -139,7 +135,6 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", - "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } }, @@ -175,7 +170,6 @@ "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", "previewnet": "b6763b4399a888c8", - "testing": "0000000000000007", "testnet": "631e88ae7f1d7c20" } } From 1d990c02d3722b6b8f8025034b486ba4f62941dc Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 20 Mar 2024 19:04:58 +0200 Subject: [PATCH 28/39] Fix the serialization tests --- cadence/tests/serialize_nft_tests.cdc | 37 ++------------------------- cadence/tests/serialize_tests.cdc | 29 --------------------- 2 files changed, 2 insertions(+), 64 deletions(-) diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index 1000bb60..678a9276 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -14,52 +14,19 @@ access(all) var mintedBlockHeight: UInt64 = 0 access(all) fun setup() { var err = Test.deployContract( - name: "ViewResolver", - path: "../contracts/standards/ViewResolver.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "Burner", - path: "../contracts/standards/Burner.cdc", - arguments: [] - ) - err = Test.deployContract( - name: "FungibleToken", - path: "../contracts/standards/FungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "NonFungibleToken", - path: "../contracts/standards/NonFungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "MetadataViews", - path: "../contracts/standards/MetadataViews.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "FungibleTokenMetadataViews", - path: "../contracts/standards/FungibleTokenMetadataViews.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( name: "ExampleNFT", path: "../contracts/example-assets/ExampleNFT.cdc", arguments: [] ) Test.expect(err, Test.beNil()) + err = Test.deployContract( name: "Serialize", path: "../contracts/utils/Serialize.cdc", arguments: [] ) Test.expect(err, Test.beNil()) + err = Test.deployContract( name: "SerializeNFT", path: "../contracts/utils/SerializeNFT.cdc", diff --git a/cadence/tests/serialize_tests.cdc b/cadence/tests/serialize_tests.cdc index b0e32a19..99a5b8a8 100644 --- a/cadence/tests/serialize_tests.cdc +++ b/cadence/tests/serialize_tests.cdc @@ -11,35 +11,6 @@ let alice = Test.createAccount() access(all) fun setup() { var err = Test.deployContract( - name: "ViewResolver", - path: "../contracts/standards/ViewResolver.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "Burner", - path: "../contracts/standards/Burner.cdc", - arguments: [] - ) - err = Test.deployContract( - name: "FungibleToken", - path: "../contracts/standards/FungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "NonFungibleToken", - path: "../contracts/standards/NonFungibleToken.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "MetadataViews", - path: "../contracts/standards/MetadataViews.cdc", - arguments: [] - ) - Test.expect(err, Test.beNil()) - err = Test.deployContract( name: "Serialize", path: "../contracts/utils/Serialize.cdc", arguments: [] From 7f1504bbc4d0b624d51dc6b6294da14846ede7ed Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:25:13 -0500 Subject: [PATCH 29/39] update FlowEVMBridgeUtils to deploy EVM factory on init --- cadence/args/deploy-factory-args.json | 8 -------- cadence/contracts/bridge/FlowEVMBridgeUtils.cdc | 11 +++++++---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/cadence/args/deploy-factory-args.json b/cadence/args/deploy-factory-args.json index d49bf2f5..52ac023c 100644 --- a/cadence/args/deploy-factory-args.json +++ b/cadence/args/deploy-factory-args.json @@ -2,13 +2,5 @@ { "type": "String", "value": "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6129f4806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611eb78062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001eb738038062001eb7833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b50600c620000a0848262000386565b50600d620000af838262000386565b50600e620000be828262000386565b5050505050505062000452565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611a5580620004626000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a76b4d56116100a2578063cd279c7c11610071578063cd279c7c146103a8578063e8a3d485146103bb578063e985e9c5146103c3578063f2fde38b146103d657600080fd5b8063a76b4d5614610372578063b49bbd941461037a578063b88d4fde14610382578063c87b56dd1461039557600080fd5b806394e29329116100de57806394e293291461034757806395d89b411461034f578063a159047b14610357578063a22cb4651461035f57600080fd5b806370a082311461031b578063715018a61461032e5780638da5cb5b1461033657600080fd5b80632f745c59116101715780634f558e791161014b5780634f558e79146102c25780634f6ccce7146102ed5780635e0a9661146103005780636352211e1461030857600080fd5b80632f745c591461028957806342842e0e1461029c57806342966c68146102af57600080fd5b8063095ea7b3116101ad578063095ea7b31461023c57806318160ddd1461025157806318e97fd11461026357806323b872dd1461027657600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611494565b6103e9565b60405190151581526020015b60405180910390f35b6102046103fa565b6040516101f39190611501565b61022461021f366004611514565b61048c565b6040516001600160a01b0390911681526020016101f3565b61024f61024a366004611549565b6104b5565b005b6009545b6040519081526020016101f3565b61024f61027136600461161f565b6104c4565b61024f610284366004611666565b6104d6565b610255610297366004611549565b610566565b61024f6102aa366004611666565b6105cb565b61024f6102bd366004611514565b6105eb565b6101e76102d0366004611514565b6000908152600260205260409020546001600160a01b0316151590565b6102556102fb366004611514565b6105f7565b610204610650565b610224610316366004611514565b61065f565b6102556103293660046116a2565b61066a565b61024f6106b2565b600b546001600160a01b0316610224565b6102046106c6565b6102046106d5565b6102046106e4565b61024f61036d3660046116bd565b610772565b61020461077d565b61020461078a565b61024f6103903660046116f9565b610797565b6102046103a3366004611514565b6107ae565b61024f6103b6366004611775565b6107b9565b6102046107d5565b6101e76103d13660046117cc565b6107e4565b61024f6103e43660046116a2565b610812565b60006103f482610850565b92915050565b606060008054610409906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610435906117ff565b80156104825780601f1061045757610100808354040283529160200191610482565b820191906000526020600020905b81548152906001019060200180831161046557829003601f168201915b5050505050905090565b600061049782610875565b506000828152600460205260409020546001600160a01b03166103f4565b6104c08282336108ae565b5050565b6104cc6108bb565b6104c082826108e8565b6001600160a01b03821661050557604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610512838333610938565b9050836001600160a01b0316816001600160a01b031614610560576040516364283d7b60e01b81526001600160a01b03808616600483015260248201849052821660448201526064016104fc565b50505050565b60006105718361066a565b82106105a25760405163295f44f760e21b81526001600160a01b0384166004820152602481018390526044016104fc565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6105e683838360405180602001604052806000815250610797565b505050565b6104c060008233610938565b600061060260095490565b821061062b5760405163295f44f760e21b815260006004820152602481018390526044016104fc565b6009828154811061063e5761063e611839565b90600052602060002001549050919050565b6060600d8054610409906117ff565b60006103f482610875565b60006001600160a01b038216610696576040516322718ad960e21b8152600060048201526024016104fc565b506001600160a01b031660009081526003602052604090205490565b6106ba6108bb565b6106c4600061094d565b565b6060600c8054610409906117ff565b606060018054610409906117ff565b600d80546106f1906117ff565b80601f016020809104026020016040519081016040528092919081815260200182805461071d906117ff565b801561076a5780601f1061073f5761010080835404028352916020019161076a565b820191906000526020600020905b81548152906001019060200180831161074d57829003601f168201915b505050505081565b6104c033838361099f565b600e80546106f1906117ff565b600c80546106f1906117ff565b6107a28484846104d6565b61056084848484610a3e565b60606103f482610b67565b6107c16108bb565b6107cb8383610c70565b6105e682826108e8565b6060600e8054610409906117ff565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61081a6108bb565b6001600160a01b03811661084457604051631e4fbdf760e01b8152600060048201526024016104fc565b61084d8161094d565b50565b60006001600160e01b0319821663780e9d6360e01b14806103f457506103f482610c8a565b6000818152600260205260408120546001600160a01b0316806103f457604051637e27328960e01b8152600481018490526024016104fc565b6105e68383836001610caf565b600b546001600160a01b031633146106c45760405163118cdaa760e01b81523360048201526024016104fc565b6000828152600660205260409020610900828261189f565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6000610945848484610db5565b949350505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166109d157604051630b61174360e31b81526001600160a01b03831660048201526024016104fc565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561056057604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610a8090339088908790879060040161195f565b6020604051808303816000875af1925050508015610abb575060408051601f3d908101601f19168201909252610ab89181019061199c565b60015b610b24573d808015610ae9576040519150601f19603f3d011682016040523d82523d6000602084013e610aee565b606091505b508051600003610b1c57604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610b6057604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b5050505050565b6060610b7282610875565b5060008281526006602052604081208054610b8c906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb8906117ff565b8015610c055780601f10610bda57610100808354040283529160200191610c05565b820191906000526020600020905b815481529060010190602001808311610be857829003601f168201915b505050505090506000610c2360408051602081019091526000815290565b90508051600003610c35575092915050565b815115610c67578082604051602001610c4f9291906119b9565b60405160208183030381529060405292505050919050565b61094584610e82565b6104c0828260405180602001604052806000815250610ef7565b60006001600160e01b03198216632483248360e11b14806103f457506103f482610f0e565b8080610cc357506001600160a01b03821615155b15610d85576000610cd384610875565b90506001600160a01b03831615801590610cff5750826001600160a01b0316816001600160a01b031614155b8015610d125750610d1081846107e4565b155b15610d3b5760405163a9fbf51f60e01b81526001600160a01b03841660048201526024016104fc565b8115610d835783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610dc3858585610f5e565b90506001600160a01b038116610e2057610e1b84600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b610e43565b846001600160a01b0316816001600160a01b031614610e4357610e438185611057565b6001600160a01b038516610e5f57610e5a846110e8565b610945565b846001600160a01b0316816001600160a01b031614610945576109458585611197565b6060610e8d82610875565b506000610ea560408051602081019091526000815290565b90506000815111610ec55760405180602001604052806000815250610ef0565b80610ecf846111e7565b604051602001610ee09291906119b9565b6040516020818303038152906040525b9392505050565b610f01838361127a565b6105e66000848484610a3e565b60006001600160e01b031982166380ac58cd60e01b1480610f3f57506001600160e01b03198216635b5e139f60e01b145b806103f457506301ffc9a760e01b6001600160e01b03198316146103f4565b6000828152600260205260408120546001600160a01b0390811690831615610f8b57610f8b8184866112df565b6001600160a01b03811615610fc957610fa8600085600080610caf565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615610ff8576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006110628361066a565b6000838152600860205260409020549091508082146110b5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009546000906110fa906001906119e8565b6000838152600a60205260408120546009805493945090928490811061112257611122611839565b90600052602060002001549050806009838154811061114357611143611839565b6000918252602080832090910192909255828152600a9091526040808220849055858252812055600980548061117b5761117b611a09565b6001900381819060005260206000200160009055905550505050565b600060016111a48461066a565b6111ae91906119e8565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b606060006111f483611343565b600101905060008167ffffffffffffffff81111561121457611214611573565b6040519080825280601f01601f19166020018201604052801561123e576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461124857509392505050565b6001600160a01b0382166112a457604051633250574960e11b8152600060048201526024016104fc565b60006112b283836000610938565b90506001600160a01b038116156105e6576040516339e3563760e11b8152600060048201526024016104fc565b6112ea83838361141b565b6105e6576001600160a01b03831661131857604051637e27328960e01b8152600481018290526024016104fc565b60405163177e802f60e01b81526001600160a01b0383166004820152602481018290526044016104fc565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113825772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113ae576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113cc57662386f26fc10000830492506010015b6305f5e10083106113e4576305f5e100830492506008015b61271083106113f857612710830492506004015b6064831061140a576064830492506002015b600a83106103f45760010192915050565b60006001600160a01b038316158015906109455750826001600160a01b0316846001600160a01b03161480611455575061145584846107e4565b806109455750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461084d57600080fd5b6000602082840312156114a657600080fd5b8135610ef08161147e565b60005b838110156114cc5781810151838201526020016114b4565b50506000910152565b600081518084526114ed8160208601602086016114b1565b601f01601f19169290920160200192915050565b602081526000610ef060208301846114d5565b60006020828403121561152657600080fd5b5035919050565b80356001600160a01b038116811461154457600080fd5b919050565b6000806040838503121561155c57600080fd5b6115658361152d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156115a4576115a4611573565b604051601f8501601f19908116603f011681019082821181831017156115cc576115cc611573565b816040528093508581528686860111156115e557600080fd5b858560208301376000602087830101525050509392505050565b600082601f83011261161057600080fd5b610ef083833560208501611589565b6000806040838503121561163257600080fd5b82359150602083013567ffffffffffffffff81111561165057600080fd5b61165c858286016115ff565b9150509250929050565b60008060006060848603121561167b57600080fd5b6116848461152d565b92506116926020850161152d565b9150604084013590509250925092565b6000602082840312156116b457600080fd5b610ef08261152d565b600080604083850312156116d057600080fd5b6116d98361152d565b9150602083013580151581146116ee57600080fd5b809150509250929050565b6000806000806080858703121561170f57600080fd5b6117188561152d565b93506117266020860161152d565b925060408501359150606085013567ffffffffffffffff81111561174957600080fd5b8501601f8101871361175a57600080fd5b61176987823560208401611589565b91505092959194509250565b60008060006060848603121561178a57600080fd5b6117938461152d565b925060208401359150604084013567ffffffffffffffff8111156117b657600080fd5b6117c2868287016115ff565b9150509250925092565b600080604083850312156117df57600080fd5b6117e88361152d565b91506117f66020840161152d565b90509250929050565b600181811c9082168061181357607f821691505b60208210810361183357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f8211156105e6576000816000526020600020601f850160051c810160208610156118785750805b601f850160051c820191505b8181101561189757828155600101611884565b505050505050565b815167ffffffffffffffff8111156118b9576118b9611573565b6118cd816118c784546117ff565b8461184f565b602080601f83116001811461190257600084156118ea5750858301515b600019600386901b1c1916600185901b178555611897565b600085815260208120601f198616915b8281101561193157888601518255948401946001909101908401611912565b508582101561194f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611992908301846114d5565b9695505050505050565b6000602082840312156119ae57600080fd5b8151610ef08161147e565b600083516119cb8184602088016114b1565b8351908301906119df8183602088016114b1565b01949350505050565b818103818111156103f457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212206ff38700c73b602455dbb7964f2d3281f62efc77263f0f3bdb67f5e4ee5d4f3f64736f6c63430008170033a26469706673582212207f55223fc039b168a1e0c0bb9dc8d219b8219d1b2151fe8e9843aecefd41f82664736f6c63430008170033" - }, - { - "type": "UInt64", - "value": "12000000" - }, - { - "type": "UFix64", - "value": "0.0" } ] \ No newline at end of file diff --git a/cadence/contracts/bridge/FlowEVMBridgeUtils.cdc b/cadence/contracts/bridge/FlowEVMBridgeUtils.cdc index b4562652..af3df80c 100644 --- a/cadence/contracts/bridge/FlowEVMBridgeUtils.cdc +++ b/cadence/contracts/bridge/FlowEVMBridgeUtils.cdc @@ -690,7 +690,7 @@ contract FlowEVMBridgeUtils { ) } - init(bridgeFactoryEVMAddress: String) { + init(bridgeFactoryBytecodeHex: String) { self.delimiter = "_" self.contractNamePrefixes = { Type<@{NonFungibleToken.NFT}>(): { @@ -700,8 +700,11 @@ contract FlowEVMBridgeUtils { "bridged": "EVMVMBridgedToken" } } - let bridgeFactoryEVMAddressBytes: [UInt8] = bridgeFactoryEVMAddress.decodeHex() - self.bridgeFactoryEVMAddress = self.getEVMAddressFromHexString(address: bridgeFactoryEVMAddress) - ?? panic("Invalid bridge factory EVM address") + // Deploy the FlowBridgeFactory.sol contract from provided bytecode and capture the deployed address + self.bridgeFactoryEVMAddress = self.borrowCOA().deploy( + code: bridgeFactoryBytecodeHex.decodeHex(), + gasLimit: 15000000, + value: EVM.Balance(attoflow: 0) + ) } } From 9bdc1dbadfccbdccdbfa837f1bcc75c2fbf02d0a Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:31:20 -0500 Subject: [PATCH 30/39] update config with testing aliases & fix serialize_nft_tests --- cadence/tests/serialize_nft_tests.cdc | 2 +- flow.json | 44 ++++++++++++++++++--------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/cadence/tests/serialize_nft_tests.cdc b/cadence/tests/serialize_nft_tests.cdc index 678a9276..982f3fa4 100644 --- a/cadence/tests/serialize_nft_tests.cdc +++ b/cadence/tests/serialize_nft_tests.cdc @@ -6,7 +6,7 @@ import "MetadataViews" import "Serialize" import "SerializeNFT" -access(all) let admin = Test.getAccount(0x0000000000000007) +access(all) let admin = Test.getAccount(0x0000000000000008) access(all) let alice = Test.createAccount() access(all) var mintedBlockHeight: UInt64 = 0 diff --git a/flow.json b/flow.json index d16493e3..a2ec42d7 100644 --- a/flow.json +++ b/flow.json @@ -3,13 +3,15 @@ "ArrayUtils": { "source": "./cadence/contracts/utils/ArrayUtils.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "BridgePermissions": { "source": "./cadence/contracts/bridge/BridgePermissions.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "Burner": { @@ -22,7 +24,8 @@ "CrossVMNFT": { "source": "./cadence/contracts/bridge/CrossVMNFT.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "EVM": { @@ -35,44 +38,50 @@ "EVMBridgeRouter": { "source": "./cadence/contracts/bridge/EVMBridgeRouter.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "ExampleNFT": { "source": "./cadence/contracts/example-assets/ExampleNFT.cdc", "aliases": { "emulator": "179b6b1cb6755e31", - "testing": "0000000000000007" + "testing": "0000000000000008" } }, "FlowEVMBridge": { "source": "./cadence/contracts/bridge/FlowEVMBridge.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "FlowEVMBridgeConfig": { "source": "./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "FlowEVMBridgeNFTEscrow": { "source": "./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "FlowEVMBridgeTemplates": { "source": "./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "FlowEVMBridgeUtils": { "source": "./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "FlowToken": { @@ -105,19 +114,22 @@ "ICrossVM": { "source": "./cadence/contracts/bridge/ICrossVM.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "IEVMBridgeNFTMinter": { "source": "./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "IFlowEVMNFTBridge": { "source": "./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "MetadataViews": { @@ -141,7 +153,8 @@ "ScopedFTProviders": { "source": "./cadence/contracts/utils/ScopedFTProviders.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "Serialize": { @@ -161,7 +174,8 @@ "StringUtils": { "source": "./cadence/contracts/utils/StringUtils.cdc", "aliases": { - "emulator": "f8d6e0586b0a20c7" + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" } }, "ViewResolver": { From 8101eb99557e6be22efeea128d00da6d797ce0b5 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:31:56 -0500 Subject: [PATCH 31/39] complete bridge test setup() & add test_helpers for consts --- cadence/tests/flow_evm_bridge_tests.cdc | 141 +++++++++++++++++++++++- cadence/tests/test_helpers.cdc | 45 ++++++++ 2 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 cadence/tests/test_helpers.cdc diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index 36e45567..cf81ed07 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -1,21 +1,158 @@ import Test import BlockchainHelpers +import "test_helpers.cdc" + access(all) let serviceAccount = Test.serviceAccount() +access(all) let bridgeAccount = Test.getAccount(0x0000000000000007) +access(all) let exampleNFTAccount = Test.getAccount(0x0000000000000008) +access(all) let exampleERC721Account = Test.createAccount() access(all) let alice = Test.createAccount() +access(all) +fun setup() { + // Deploy supporting util contracts + var err = Test.deployContract( + name: "ArrayUtils", + path: "../contracts/utils/ArrayUtils.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "StringUtils", + path: "../contracts/utils/StringUtils.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "ScopedFTProviders", + path: "../contracts/utils/ScopedFTProviders.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "Serialize", + path: "../contracts/utils/Serialize.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "SerializeNFT", + path: "../contracts/utils/SerializeNFT.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + // Update EVM contract with proposed bridge-supporting COA integration + let updateResult = executeTransaction( + "../transactions/test/update_contract.cdc", + ["EVM", getEVMUpdateCode()], + serviceAccount + ) + Test.expect(updateResult, Test.beSucceeded()) + // Transfer bridge account some $FLOW + let transferFlowResult = executeTransaction( + "../transactions/flow-token/transfer_flow.cdc", + [bridgeAccount.address, 10_000.0], + serviceAccount + ) + Test.expect(transferFlowResult, Test.beSucceeded()) + // Configure bridge account with a COA + let createCOAResult = executeTransaction( + "../transactions/evm/create_account.cdc", + [1_000.0], + bridgeAccount + ) + Test.expect(createCOAResult, Test.beSucceeded()) + + err = Test.deployContract( + name: "BridgePermissions", + path: "../contracts/bridge/BridgePermissions.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "ICrossVM", + path: "../contracts/bridge/ICrossVM.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "CrossVMNFT", + path: "../contracts/bridge/CrossVMNFT.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FlowEVMBridgeConfig", + path: "../contracts/bridge/FlowEVMBridgeConfig.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FlowEVMBridgeUtils", + path: "../contracts/bridge/FlowEVMBridgeUtils.cdc", + arguments: [getCompiledFactoryBytecode()] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FlowEVMBridgeNFTEscrow", + path: "../contracts/bridge/FlowEVMBridgeNFTEscrow.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FlowEVMBridgeTemplates", + path: "../contracts/bridge/FlowEVMBridgeTemplates.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + // Commit bridged NFT code + let bridgedNFTChunkResult = executeTransaction( + "../transactions/bridge/admin/upsert_contract_code_chunks.cdc", + ["bridgedNFT", getBridgedNFTCodeChunks()], + bridgeAccount + ) + Test.expect(bridgedNFTChunkResult, Test.beSucceeded()) + + err = Test.deployContract( + name: "IEVMBridgeNFTMinter", + path: "../contracts/bridge/IEVMBridgeNFTMinter.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "IFlowEVMNFTBridge", + path: "../contracts/bridge/IFlowEVMNFTBridge.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "FlowEVMBridge", + path: "../contracts/bridge/FlowEVMBridge.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "EVMBridgeRouter", + path: "../contracts/bridge/EVMBridgeRouter.cdc", + arguments: [serviceAccount.address, "FlowEVMBridge"] + ) + Test.expect(err, Test.beNil()) +} + access(all) fun testCreateCOASucceeds() { let transferFlowResult = executeTransaction( "../transactions/flow-token/transfer_flow.cdc", - [alice.address, 1000.0], + [alice.address, 1_000.0], serviceAccount ) Test.expect(transferFlowResult, Test.beSucceeded()) let createCOAResult = executeTransaction( "../transactions/evm/create_account.cdc", - [1000.0], + [100.0], alice ) Test.expect(createCOAResult, Test.beSucceeded()) diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc new file mode 100644 index 00000000..63516db9 --- /dev/null +++ b/cadence/tests/test_helpers.cdc @@ -0,0 +1,45 @@ +access(all) let evmUpdateCode = "696d706f72742043727970746f0a0a696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a61636365737328616c6c290a636f6e74726163742045564d207b0a0a202020202f2f20456e7469746c656d656e747320656e61626c696e672066696e65722d6772616e65642061636365737320636f6e74726f6c206f6e206120436164656e63654f776e65644163636f756e740a2020202061636365737328616c6c2920656e7469746c656d656e742056616c69646174650a2020202061636365737328616c6c2920656e7469746c656d656e742057697468647261770a2020202061636365737328616c6c2920656e7469746c656d656e742043616c6c0a2020202061636365737328616c6c2920656e7469746c656d656e74204465706c6f790a2020202061636365737328616c6c2920656e7469746c656d656e74204f776e65720a2020202061636365737328616c6c2920656e7469746c656d656e74204272696467650a0a2020202061636365737328616c6c290a202020206576656e7420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a205b55496e74383b2032305d290a0a202020202f2f2f2045564d4164647265737320697320616e2045564d2d636f6d70617469626c6520616464726573730a2020202061636365737328616c6c290a202020207374727563742045564d41646472657373207b0a0a20202020202020202f2f2f204279746573206f662074686520616464726573730a202020202020202061636365737328616c6c290a20202020202020206c65742062797465733a205b55496e74383b2032305d0a0a20202020202020202f2f2f20436f6e737472756374732061206e65772045564d20616464726573732066726f6d2074686520676976656e206279746520726570726573656e746174696f6e0a20202020202020207669657720696e69742862797465733a205b55496e74383b2032305d29207b0a20202020202020202020202073656c662e6279746573203d2062797465730a20202020202020207d0a0a20202020202020202f2f2f2042616c616e6365206f662074686520616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a2020202020202020202020206c65742062616c616e6365203d20496e7465726e616c45564d2e62616c616e6365280a20202020202020202020202020202020616464726573733a2073656c662e62797465730a202020202020202020202020290a20202020202020202020202072657475726e2042616c616e6365286174746f666c6f773a2062616c616e6365290a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207374727563742042616c616e6365207b0a0a20202020202020202f2f2f205468652062616c616e636520696e206174746f2d464c4f570a20202020202020202f2f2f204174746f2d464c4f572069732074686520736d616c6c6573742064656e6f6d696e6174696f6e206f6620464c4f5720283165313820464c4f57290a20202020202020202f2f2f2074686174206973207573656420746f2073746f7265206163636f756e742062616c616e63657320696e736964652045564d0a20202020202020202f2f2f2073696d696c617220746f207468652077617920574549206973207573656420746f2073746f72652045544820646976697369626c6520746f20313820646563696d616c20706c616365732e0a202020202020202061636365737328616c6c290a2020202020202020766172206174746f666c6f773a2055496e740a0a20202020202020202f2f2f20436f6e737472756374732061206e65772062616c616e63650a202020202020202061636365737328616c6c290a20202020202020207669657720696e6974286174746f666c6f773a2055496e7429207b0a20202020202020202020202073656c662e6174746f666c6f77203d206174746f666c6f770a20202020202020207d0a0a20202020202020202f2f2f2053657473207468652062616c616e636520627920612055466978363420283820646563696d616c20706f696e7473292c2074686520666f726d61740a20202020202020202f2f2f2074686174206973207573656420696e20436164656e636520746f2073746f726520464c4f5720746f6b656e732e0a202020202020202061636365737328616c6c290a202020202020202066756e20736574464c4f5728666c6f773a20554669783634297b0a20202020202020202020202073656c662e6174746f666c6f77203d20496e7465726e616c45564d2e63617374546f4174746f464c4f572862616c616e63653a20666c6f77290a20202020202020207d0a0a20202020202020202f2f2f204361737473207468652062616c616e636520746f2061205546697836342028726f756e64696e6720646f776e290a20202020202020202f2f2f205761726e696e67212063617374696e6720612062616c616e636520746f20612055466978363420776869636820737570706f7274732061206c6f776572206c6576656c206f6620707265636973696f6e0a20202020202020202f2f2f20283820646563696d616c20706f696e747320696e20636f6d7061726520746f20313829206d6967687420726573756c7420696e20726f756e64696e6720646f776e206572726f722e0a20202020202020202f2f2f205573652074686520746f4174746f466c6f772066756e6374696f6e20696620796f752063617265206e656564206d6f72652061636375726163792e0a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e464c4f5728293a20554669783634207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63617374546f464c4f572862616c616e63653a2073656c662e6174746f666c6f77290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e73207468652062616c616e636520696e204174746f2d464c4f570a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e4174746f464c4f5728293a2055496e74207b0a20202020202020202020202072657475726e2073656c662e6174746f666c6f770a20202020202020207d0a202020207d0a0a202020202f2f2f207265706f7274732074686520737461747573206f662065766d20657865637574696f6e2e0a2020202061636365737328616c6c2920656e756d205374617475733a2055496e7438207b0a20202020202020202f2f2f2069732028726172656c79292072657475726e6564207768656e2073746174757320697320756e6b6e6f776e0a20202020202020202f2f2f20616e6420736f6d657468696e672068617320676f6e6520766572792077726f6e672e0a202020202020202061636365737328616c6c29206361736520756e6b6e6f776e0a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206661696c6564206174207468652076616c69646174696f6e20737465702028652e672e206e6f6e6365206d69736d61746368292e0a20202020202020202f2f2f20416e20696e76616c6964207472616e73616374696f6e2f63616c6c2069732072656a656374656420746f2062652065786563757465640a20202020202020202f2f2f206f7220626520696e636c7564656420696e206120626c6f636b2e0a202020202020202061636365737328616c6c29206361736520696e76616c69640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c206275742074686520766d20686173207265706f7274656420616e206572726f722061730a20202020202020202f2f2f20746865206f7574636f6d65206f6620657865637574696f6e2028652e672e2072756e6e696e67206f7574206f6620676173292e0a20202020202020202f2f2f2041206661696c65642074782f63616c6c20697320696e636c7564656420696e206120626c6f636b2e0a20202020202020202f2f2f204e6f746520746861742072657375626d697373696f6e206f662061206661696c6564207472616e73616374696f6e20776f756c640a20202020202020202f2f2f20726573756c7420696e20696e76616c69642073746174757320696e20746865207365636f6e6420617474656d70742c20676976656e0a20202020202020202f2f2f20746865206e6f6e636520776f756c6420626520636f6d6520696e76616c69642e0a202020202020202061636365737328616c6c292063617365206661696c65640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c20616e64206e6f206572726f72206973207265706f727465642062792074686520766d2e0a202020202020202061636365737328616c6c292063617365207375636365737366756c0a202020207d0a0a202020202f2f2f207265706f72747320746865206f7574636f6d65206f662065766d207472616e73616374696f6e2f63616c6c20657865637574696f6e20617474656d70740a2020202061636365737328616c6c292073747275637420526573756c74207b0a20202020202020202f2f2f20737461747573206f662074686520657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c6574207374617475733a205374617475730a0a20202020202020202f2f2f206572726f7220636f646520286572726f7220636f6465207a65726f206d65616e73206e6f206572726f72290a202020202020202061636365737328616c6c290a20202020202020206c6574206572726f72436f64653a2055496e7436340a0a20202020202020202f2f2f2072657475726e732074686520616d6f756e74206f6620676173206d65746572656420647572696e670a20202020202020202f2f2f2065766d20657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c657420676173557365643a2055496e7436340a0a20202020202020202f2f2f2072657475726e7320746865206461746120746861742069732072657475726e65642066726f6d0a20202020202020202f2f2f207468652065766d20666f72207468652063616c6c2e20466f7220636f612e6465706c6f790a20202020202020202f2f2f2063616c6c732069742072657475726e73207468652061646472657373206279746573206f66207468650a20202020202020202f2f2f206e65776c79206465706c6f79656420636f6e74726163742e0a202020202020202061636365737328616c6c290a20202020202020206c657420646174613a205b55496e74385d0a0a2020202020202020696e6974280a2020202020202020202020207374617475733a205374617475732c0a2020202020202020202020206572726f72436f64653a2055496e7436342c0a202020202020202020202020676173557365643a2055496e7436342c0a202020202020202020202020646174613a205b55496e74385d0a202020202020202029207b0a20202020202020202020202073656c662e737461747573203d207374617475730a20202020202020202020202073656c662e6572726f72436f6465203d206572726f72436f64650a20202020202020202020202073656c662e67617355736564203d20676173557365640a20202020202020202020202073656c662e64617461203d20646174610a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204164647265737361626c65207b0a20202020202020202f2f2f205468652045564d20616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d416464726573730a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520436164656e63654f776e65644163636f756e743a204164647265737361626c65207b0a0a20202020202020206163636573732873656c66290a2020202020202020766172206164647265737342797465733a205b55496e74383b2032305d0a0a2020202020202020696e69742829207b0a2020202020202020202020202f2f206164647265737320697320696e697469616c6c792073657420746f207a65726f0a2020202020202020202020202f2f206275742075706461746564207468726f75676820696e697441646472657373206c617465720a2020202020202020202020202f2f207765206861766520746f20646f20746869732073696e6365207765206e656564207265736f75726365206964202875756964290a2020202020202020202020202f2f20746f2063616c63756c617465207468652045564d206164647265737320666f72207468697320636164656e6365206f776e6564206163636f756e740a20202020202020202020202073656c662e616464726573734279746573203d205b302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20305d0a20202020202020207d0a0a202020202020202061636365737328636f6e7472616374290a202020202020202066756e20696e697441646472657373286164647265737342797465733a205b55496e74383b2032305d29207b0a20202020202020202020202f2f206f6e6c7920616c6c6f7720736574206164647265737320666f72207468652066697273742074696d650a20202020202020202020202f2f20636865636b206164647265737320697320656d7074790a202020202020202020202020666f72206974656d20696e2073656c662e616464726573734279746573207b0a20202020202020202020202020202020617373657274286974656d203d3d20302c206d6573736167653a2022616464726573732062797465206973206e6f7420656d70747922290a2020202020202020202020207d0a202020202020202020202073656c662e616464726573734279746573203d206164647265737342797465730a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d41646472657373207b0a2020202020202020202020202f2f20416c77617973206372656174652061206e65772045564d4164647265737320696e7374616e63650a20202020202020202020202072657475726e2045564d416464726573732862797465733a2073656c662e616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f204765742062616c616e6365206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a20202020202020202020202072657475726e2073656c662e6164647265737328292e62616c616e636528290a20202020202020207d0a0a20202020202020202f2f2f204465706f736974732074686520676976656e207661756c7420696e746f2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369742866726f6d3a2040466c6f77546f6b656e2e5661756c7429207b0a202020202020202020202020496e7465726e616c45564d2e6465706f736974280a2020202020202020202020202020202066726f6d3a203c2d66726f6d2c0a20202020202020202020202020202020746f3a2073656c662e6164647265737342797465730a202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e7420626568696e6420616e20656e7469746c656d656e742c20616374696e672061732070726f6f66206f66206163636573730a2020202020202020616363657373284f776e6572207c2056616c6964617465290a2020202020202020766965772066756e2070726f7465637465644164647265737328293a2045564d41646472657373207b0a20202020202020202020202072657475726e2073656c662e6164647265737328290a20202020202020207d0a0a20202020202020202f2f2f20576974686472617773207468652062616c616e63652066726f6d2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a20202020202020202f2f2f204e6f7465207468617420616d6f756e747320736d616c6c6572207468616e2031306e4620283130652d38292063616e27742062652077697468647261776e0a20202020202020202f2f2f20676976656e207468617420466c6f7720546f6b656e205661756c747320757365205546697836347320746f2073746f72652062616c616e6365732e0a20202020202020202f2f2f2049662074686520676976656e2062616c616e636520636f6e76657273696f6e20746f2055466978363420726573756c747320696e0a20202020202020202f2f2f20726f756e64696e67206572726f722c20746869732066756e6374696f6e20776f756c64206661696c2e0a2020202020202020616363657373284f776e6572207c205769746864726177290a202020202020202066756e2077697468647261772862616c616e63653a2042616c616e6365293a2040466c6f77546f6b656e2e5661756c74207b0a2020202020202020202020206c6574207661756c74203c2d20496e7465726e616c45564d2e7769746864726177280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020616d6f756e743a2062616c616e63652e6174746f666c6f770a20202020202020202020202029206173212040466c6f77546f6b656e2e5661756c740a20202020202020202020202072657475726e203c2d7661756c740a20202020202020207d0a0a20202020202020202f2f2f204465706c6f7973206120636f6e747261637420746f207468652045564d20656e7669726f6e6d656e742e0a20202020202020202f2f2f2052657475726e73207468652061646472657373206f6620746865206e65776c79206465706c6f79656420636f6e74726163740a2020202020202020616363657373284f776e6572207c204465706c6f79290a202020202020202066756e206465706c6f79280a202020202020202020202020636f64653a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a2045564d41646472657373207b0a2020202020202020202020206c657420616464726573734279746573203d20496e7465726e616c45564d2e6465706c6f79280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020636f64653a20636f64652c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020290a20202020202020202020202072657475726e2045564d416464726573732862797465733a20616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f2043616c6c7320612066756e6374696f6e20776974682074686520676976656e20646174612e0a20202020202020202f2f2f2054686520657865637574696f6e206973206c696d697465642062792074686520676976656e20616d6f756e74206f66206761730a2020202020202020616363657373284f776e6572207c2043616c6c290a202020202020202066756e2063616c6c280a202020202020202020202020746f3a2045564d416464726573732c0a202020202020202020202020646174613a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a20526573756c74207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63616c6c280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020746f3a20746f2e62797465732c0a20202020202020202020202020202020646174613a20646174612c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020292061732120526573756c740a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a202020202020202029207b0a20202020202020202020202045564d2e626f72726f774272696467654163636573736f7228292e6465706f7369744e4654286e66743a203c2d6e66742c20746f3a2073656c662e6164647265737328292c2066656550726f76696465723a2066656550726f7669646572290a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a2020202020202020616363657373284f776e6572207c20427269646765290a202020202020202066756e2077697468647261774e4654280a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a20202020202020202020202072657475726e203c2d2045564d2e626f72726f774272696467654163636573736f7228292e77697468647261774e4654280a2020202020202020202020202020202063616c6c65723a202673656c6620617320617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a20202020202020202020202020202020747970653a20747970652c0a2020202020202020202020202020202069643a2069642c0a2020202020202020202020202020202066656550726f76696465723a2066656550726f76696465720a202020202020202020202020290a20202020202020207d0a202020207d0a0a202020202f2f2f20437265617465732061206e657720636164656e6365206f776e6564206163636f756e740a2020202061636365737328616c6c290a2020202066756e20637265617465436164656e63654f776e65644163636f756e7428293a2040436164656e63654f776e65644163636f756e74207b0a20202020202020206c657420616363203c2d63726561746520436164656e63654f776e65644163636f756e7428290a20202020202020206c65742061646472203d20496e7465726e616c45564d2e637265617465436164656e63654f776e65644163636f756e7428757569643a206163632e75756964290a20202020202020206163632e696e697441646472657373286164647265737342797465733a2061646472290a2020202020202020656d697420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a2061646472290a202020202020202072657475726e203c2d6163630a202020207d0a0a202020202f2f2f2052756e7320616e206120524c502d656e636f6465642045564d207472616e73616374696f6e2c2064656475637473207468652067617320666565732c0a202020202f2f2f20616e64206465706f736974732074686520676173206665657320696e746f207468652070726f766964656420636f696e6261736520616464726573732e0a2020202061636365737328616c6c290a2020202066756e2072756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a202020202020202072657475726e20496e7465726e616c45564d2e72756e280a2020202020202020202020202020202074783a2074782c0a20202020202020202020202020202020636f696e626173653a20636f696e626173652e62797465730a2020202020202020292061732120526573756c740a202020207d0a0a202020202f2f2f206d75737452756e2072756e7320746865207472616e73616374696f6e207573696e672045564d2e72756e207965742069740a202020202f2f2f20726f6c6c6261636b2069662074686520747820657865637574696f6e2073746174757320697320756e6b6e6f776e206f7220696e76616c69642e0a202020202f2f2f204e6f746520746861742074686973206d6574686f6420646f6573206e6f7420726f6c6c6261636b206966207472616e73616374696f6e0a202020202f2f2f2069732065786563757465642062757420616e20766d206572726f72206973207265706f7274656420617320746865206f7574636f6d650a202020202f2f2f206f662074686520657865637574696f6e20287374617475733a206661696c6564292e0a2020202061636365737328616c6c290a2020202066756e206d75737452756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a20202020202020206c65742072756e526573756c74203d2073656c662e72756e2874783a2074782c20636f696e626173653a20636f696e62617365290a2020202020202020617373657274280a20202020202020202020202072756e526573756c742e737461747573203d3d205374617475732e6661696c6564207c7c2072756e526573756c742e737461747573203d3d205374617475732e7375636365737366756c2c0a2020202020202020202020206d6573736167653a20227478206973206e6f742076616c696420666f7220657865637574696f6e220a2020202020202020290a202020202020202072657475726e2072756e526573756c740a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249285f2076616c7565733a205b416e795374727563745d293a205b55496e74385d207b0a202020202020202072657475726e20496e7465726e616c45564d2e656e636f64654142492876616c756573290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f64654142492874797065733a205b547970655d2c20646174613a205b55496e74385d293a205b416e795374727563745d207b0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a20202020202020205f2076616c7565733a205b416e795374727563745d0a20202020293a205b55496e74385d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a20202020202020206c657420617267756d656e7473203d20496e7465726e616c45564d2e656e636f64654142492876616c756573290a0a202020202020202072657475726e206d6574686f6449442e636f6e63617428617267756d656e7473290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a202020202020202074797065733a205b547970655d2c0a2020202020202020646174613a205b55496e74385d0a20202020293a205b416e795374727563745d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a0a2020202020202020666f72206279746520696e206d6574686f644944207b0a2020202020202020202020206966206279746520213d20646174612e72656d6f766546697273742829207b0a2020202020202020202020202020202070616e696328227369676e6174757265206d69736d6174636822290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a202020202f2f2f2056616c69646174696f6e526573756c742072657475726e732074686520726573756c74206f6620434f41206f776e6572736869702070726f6f662076616c69646174696f6e0a2020202061636365737328616c6c290a202020207374727563742056616c69646174696f6e526573756c74207b0a202020202020202061636365737328616c6c290a20202020202020206c657420697356616c69643a20426f6f6c0a0a202020202020202061636365737328616c6c290a20202020202020206c65742070726f626c656d3a20537472696e673f0a0a2020202020202020696e697428697356616c69643a20426f6f6c2c2070726f626c656d3a20537472696e673f29207b0a20202020202020202020202073656c662e697356616c6964203d20697356616c69640a20202020202020202020202073656c662e70726f626c656d203d2070726f626c656d0a20202020202020207d0a202020207d0a0a202020202f2f2f2076616c6964617465434f414f776e65727368697050726f6f662076616c696461746573206120434f41206f776e6572736869702070726f6f660a2020202061636365737328616c6c290a2020202066756e2076616c6964617465434f414f776e65727368697050726f6f66280a2020202020202020616464726573733a20416464726573732c0a2020202020202020706174683a205075626c6963506174682c0a20202020202020207369676e6564446174613a205b55496e74385d2c0a20202020202020206b6579496e64696365733a205b55496e7436345d2c0a20202020202020207369676e6174757265733a205b5b55496e74385d5d2c0a202020202020202065766d416464726573733a205b55496e74383b2032305d0a20202020293a2056616c69646174696f6e526573756c74207b0a0a20202020202020202f2f206d616b65207369676e6174757265207365742066697273740a20202020202020202f2f20636865636b206e756d626572206f66207369676e617475726573206d617463686573206e756d626572206f66206b657920696e64696365730a20202020202020206966206b6579496e64696365732e6c656e67746820213d207369676e6174757265732e6c656e677468207b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a20226b657920696e64696365732073697a6520646f65736e2774206d6174636820746865207369676e617475726573220a202020202020202020202020290a20202020202020207d0a0a2020202020202020766172207369676e61747572655365743a205b43727970746f2e4b65794c6973745369676e61747572655d203d205b5d0a2020202020202020666f72207369676e6174757265496e6465782c207369676e617475726520696e207369676e6174757265737b0a2020202020202020202020207369676e61747572655365742e617070656e642843727970746f2e4b65794c6973745369676e6174757265280a202020202020202020202020202020206b6579496e6465783a20496e74286b6579496e64696365735b7369676e6174757265496e6465785d292c0a202020202020202020202020202020207369676e61747572653a207369676e61747572650a20202020202020202020202029290a20202020202020207d0a0a20202020202020202f2f206665746368206163636f756e740a20202020202020206c657420616363203d206765744163636f756e742861646472657373290a0a20202020202020202f2f20636f6e737472756374696e67206b6579206c6973740a20202020202020206c6574206b65794c697374203d2043727970746f2e4b65794c69737428290a2020202020202020666f72207369676e617475726520696e207369676e6174757265536574207b0a2020202020202020202020206c6574206b6579203d206163632e6b6579732e676574286b6579496e6465783a207369676e61747572652e6b6579496e64657829210a20202020202020202020202061737365727428216b65792e69735265766f6b65642c206d6573736167653a20227265766f6b6564206b6579206973207573656422290a2020202020202020202020206b65794c6973742e616464280a20202020202020202020202020206b65792e7075626c69634b65792c0a202020202020202020202020202068617368416c676f726974686d3a206b65792e68617368416c676f726974686d2c0a20202020202020202020202020207765696768743a206b65792e7765696768742c0a2020202020202020202020290a20202020202020207d0a0a20202020202020206c657420697356616c6964203d206b65794c6973742e766572696679280a2020202020202020202020207369676e61747572655365743a207369676e61747572655365742c0a2020202020202020202020207369676e6564446174613a207369676e6564446174612c0a202020202020202020202020646f6d61696e53657061726174696f6e5461673a2022464c4f572d56302e302d75736572220a2020202020202020290a0a202020202020202069662021697356616c69647b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a202274686520676976656e207369676e61747572657320617265206e6f742076616c6964206f722070726f7669646520656e6f75676820776569676874220a202020202020202020202020290a20202020202020207d0a0a20202020202020206c657420636f61526566203d206163632e6361706162696c69746965732e626f72726f773c2645564d2e436164656e63654f776e65644163636f756e743e2870617468290a0a2020202020202020696620636f61526566203d3d206e696c207b0a2020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202070726f626c656d3a2022636f756c64206e6f7420626f72726f7720627269646765206163636f756e742773207265736f75726365220a20202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f207665726966792065766d2061646472657373206d61746368696e670a20202020202020207661722061646472203d20636f61526566212e6164647265737328290a2020202020202020666f7220696e6465782c206974656d20696e20636f61526566212e6164647265737328292e6279746573207b0a2020202020202020202020206966206974656d20213d2065766d416464726573735b696e6465785d207b0a2020202020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202020202070726f626c656d3a202265766d2061646472657373206d69736d61746368220a20202020202020202020202020202020290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e2056616c69646174696f6e526573756c74280a202020202020202020202020697356616c69643a20747275652c0a20202020202020202020202070726f626c656d3a206e696c0a2020202020202020290a202020207d0a0a202020202f2f2f2052657475726e732061207265666572656e636520746f20746865204272696467654163636573736f722064657369676e6174656420666f7220696e7465726e616c206272696467652072657175657374730a202020206163636573732873656c66290a20202020766965772066756e20626f72726f774272696467654163636573736f7228293a2061757468284272696467652920267b4272696467654163636573736f727d207b0a202020202020202072657475726e2073656c662e6163636f756e742e73746f726167652e626f72726f773c61757468284272696467652920267b4272696467654163636573736f727d3e2866726f6d3a202f73746f726167652f65766d427269646765526f75746572290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f77207265666572656e636520746f207468652045564d2062726964676522290a202020207d0a0a202020202f2f2f20496e7465726661636520666f722061207265736f75726365207768696368206163747320617320616e20656e747279706f696e7420746f2074686520564d206272696467650a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204272696467654163636573736f72207b0a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e465420746f2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a202020202020202020202020746f3a2045564d2e45564d416464726573732c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020290a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e46542066726f6d2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e2077697468647261774e4654280a20202020202020202020202063616c6c65723a20617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d0a202020207d0a7d0a" + +access(all) let compiledFactoryBytecode = "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6129f4806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611eb78062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001eb738038062001eb7833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b50600c620000a0848262000386565b50600d620000af838262000386565b50600e620000be828262000386565b5050505050505062000452565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611a5580620004626000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a76b4d56116100a2578063cd279c7c11610071578063cd279c7c146103a8578063e8a3d485146103bb578063e985e9c5146103c3578063f2fde38b146103d657600080fd5b8063a76b4d5614610372578063b49bbd941461037a578063b88d4fde14610382578063c87b56dd1461039557600080fd5b806394e29329116100de57806394e293291461034757806395d89b411461034f578063a159047b14610357578063a22cb4651461035f57600080fd5b806370a082311461031b578063715018a61461032e5780638da5cb5b1461033657600080fd5b80632f745c59116101715780634f558e791161014b5780634f558e79146102c25780634f6ccce7146102ed5780635e0a9661146103005780636352211e1461030857600080fd5b80632f745c591461028957806342842e0e1461029c57806342966c68146102af57600080fd5b8063095ea7b3116101ad578063095ea7b31461023c57806318160ddd1461025157806318e97fd11461026357806323b872dd1461027657600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611494565b6103e9565b60405190151581526020015b60405180910390f35b6102046103fa565b6040516101f39190611501565b61022461021f366004611514565b61048c565b6040516001600160a01b0390911681526020016101f3565b61024f61024a366004611549565b6104b5565b005b6009545b6040519081526020016101f3565b61024f61027136600461161f565b6104c4565b61024f610284366004611666565b6104d6565b610255610297366004611549565b610566565b61024f6102aa366004611666565b6105cb565b61024f6102bd366004611514565b6105eb565b6101e76102d0366004611514565b6000908152600260205260409020546001600160a01b0316151590565b6102556102fb366004611514565b6105f7565b610204610650565b610224610316366004611514565b61065f565b6102556103293660046116a2565b61066a565b61024f6106b2565b600b546001600160a01b0316610224565b6102046106c6565b6102046106d5565b6102046106e4565b61024f61036d3660046116bd565b610772565b61020461077d565b61020461078a565b61024f6103903660046116f9565b610797565b6102046103a3366004611514565b6107ae565b61024f6103b6366004611775565b6107b9565b6102046107d5565b6101e76103d13660046117cc565b6107e4565b61024f6103e43660046116a2565b610812565b60006103f482610850565b92915050565b606060008054610409906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610435906117ff565b80156104825780601f1061045757610100808354040283529160200191610482565b820191906000526020600020905b81548152906001019060200180831161046557829003601f168201915b5050505050905090565b600061049782610875565b506000828152600460205260409020546001600160a01b03166103f4565b6104c08282336108ae565b5050565b6104cc6108bb565b6104c082826108e8565b6001600160a01b03821661050557604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610512838333610938565b9050836001600160a01b0316816001600160a01b031614610560576040516364283d7b60e01b81526001600160a01b03808616600483015260248201849052821660448201526064016104fc565b50505050565b60006105718361066a565b82106105a25760405163295f44f760e21b81526001600160a01b0384166004820152602481018390526044016104fc565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6105e683838360405180602001604052806000815250610797565b505050565b6104c060008233610938565b600061060260095490565b821061062b5760405163295f44f760e21b815260006004820152602481018390526044016104fc565b6009828154811061063e5761063e611839565b90600052602060002001549050919050565b6060600d8054610409906117ff565b60006103f482610875565b60006001600160a01b038216610696576040516322718ad960e21b8152600060048201526024016104fc565b506001600160a01b031660009081526003602052604090205490565b6106ba6108bb565b6106c4600061094d565b565b6060600c8054610409906117ff565b606060018054610409906117ff565b600d80546106f1906117ff565b80601f016020809104026020016040519081016040528092919081815260200182805461071d906117ff565b801561076a5780601f1061073f5761010080835404028352916020019161076a565b820191906000526020600020905b81548152906001019060200180831161074d57829003601f168201915b505050505081565b6104c033838361099f565b600e80546106f1906117ff565b600c80546106f1906117ff565b6107a28484846104d6565b61056084848484610a3e565b60606103f482610b67565b6107c16108bb565b6107cb8383610c70565b6105e682826108e8565b6060600e8054610409906117ff565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61081a6108bb565b6001600160a01b03811661084457604051631e4fbdf760e01b8152600060048201526024016104fc565b61084d8161094d565b50565b60006001600160e01b0319821663780e9d6360e01b14806103f457506103f482610c8a565b6000818152600260205260408120546001600160a01b0316806103f457604051637e27328960e01b8152600481018490526024016104fc565b6105e68383836001610caf565b600b546001600160a01b031633146106c45760405163118cdaa760e01b81523360048201526024016104fc565b6000828152600660205260409020610900828261189f565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6000610945848484610db5565b949350505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166109d157604051630b61174360e31b81526001600160a01b03831660048201526024016104fc565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561056057604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610a8090339088908790879060040161195f565b6020604051808303816000875af1925050508015610abb575060408051601f3d908101601f19168201909252610ab89181019061199c565b60015b610b24573d808015610ae9576040519150601f19603f3d011682016040523d82523d6000602084013e610aee565b606091505b508051600003610b1c57604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610b6057604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b5050505050565b6060610b7282610875565b5060008281526006602052604081208054610b8c906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb8906117ff565b8015610c055780601f10610bda57610100808354040283529160200191610c05565b820191906000526020600020905b815481529060010190602001808311610be857829003601f168201915b505050505090506000610c2360408051602081019091526000815290565b90508051600003610c35575092915050565b815115610c67578082604051602001610c4f9291906119b9565b60405160208183030381529060405292505050919050565b61094584610e82565b6104c0828260405180602001604052806000815250610ef7565b60006001600160e01b03198216632483248360e11b14806103f457506103f482610f0e565b8080610cc357506001600160a01b03821615155b15610d85576000610cd384610875565b90506001600160a01b03831615801590610cff5750826001600160a01b0316816001600160a01b031614155b8015610d125750610d1081846107e4565b155b15610d3b5760405163a9fbf51f60e01b81526001600160a01b03841660048201526024016104fc565b8115610d835783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610dc3858585610f5e565b90506001600160a01b038116610e2057610e1b84600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b610e43565b846001600160a01b0316816001600160a01b031614610e4357610e438185611057565b6001600160a01b038516610e5f57610e5a846110e8565b610945565b846001600160a01b0316816001600160a01b031614610945576109458585611197565b6060610e8d82610875565b506000610ea560408051602081019091526000815290565b90506000815111610ec55760405180602001604052806000815250610ef0565b80610ecf846111e7565b604051602001610ee09291906119b9565b6040516020818303038152906040525b9392505050565b610f01838361127a565b6105e66000848484610a3e565b60006001600160e01b031982166380ac58cd60e01b1480610f3f57506001600160e01b03198216635b5e139f60e01b145b806103f457506301ffc9a760e01b6001600160e01b03198316146103f4565b6000828152600260205260408120546001600160a01b0390811690831615610f8b57610f8b8184866112df565b6001600160a01b03811615610fc957610fa8600085600080610caf565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615610ff8576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006110628361066a565b6000838152600860205260409020549091508082146110b5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009546000906110fa906001906119e8565b6000838152600a60205260408120546009805493945090928490811061112257611122611839565b90600052602060002001549050806009838154811061114357611143611839565b6000918252602080832090910192909255828152600a9091526040808220849055858252812055600980548061117b5761117b611a09565b6001900381819060005260206000200160009055905550505050565b600060016111a48461066a565b6111ae91906119e8565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b606060006111f483611343565b600101905060008167ffffffffffffffff81111561121457611214611573565b6040519080825280601f01601f19166020018201604052801561123e576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461124857509392505050565b6001600160a01b0382166112a457604051633250574960e11b8152600060048201526024016104fc565b60006112b283836000610938565b90506001600160a01b038116156105e6576040516339e3563760e11b8152600060048201526024016104fc565b6112ea83838361141b565b6105e6576001600160a01b03831661131857604051637e27328960e01b8152600481018290526024016104fc565b60405163177e802f60e01b81526001600160a01b0383166004820152602481018290526044016104fc565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113825772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113ae576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113cc57662386f26fc10000830492506010015b6305f5e10083106113e4576305f5e100830492506008015b61271083106113f857612710830492506004015b6064831061140a576064830492506002015b600a83106103f45760010192915050565b60006001600160a01b038316158015906109455750826001600160a01b0316846001600160a01b03161480611455575061145584846107e4565b806109455750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461084d57600080fd5b6000602082840312156114a657600080fd5b8135610ef08161147e565b60005b838110156114cc5781810151838201526020016114b4565b50506000910152565b600081518084526114ed8160208601602086016114b1565b601f01601f19169290920160200192915050565b602081526000610ef060208301846114d5565b60006020828403121561152657600080fd5b5035919050565b80356001600160a01b038116811461154457600080fd5b919050565b6000806040838503121561155c57600080fd5b6115658361152d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156115a4576115a4611573565b604051601f8501601f19908116603f011681019082821181831017156115cc576115cc611573565b816040528093508581528686860111156115e557600080fd5b858560208301376000602087830101525050509392505050565b600082601f83011261161057600080fd5b610ef083833560208501611589565b6000806040838503121561163257600080fd5b82359150602083013567ffffffffffffffff81111561165057600080fd5b61165c858286016115ff565b9150509250929050565b60008060006060848603121561167b57600080fd5b6116848461152d565b92506116926020850161152d565b9150604084013590509250925092565b6000602082840312156116b457600080fd5b610ef08261152d565b600080604083850312156116d057600080fd5b6116d98361152d565b9150602083013580151581146116ee57600080fd5b809150509250929050565b6000806000806080858703121561170f57600080fd5b6117188561152d565b93506117266020860161152d565b925060408501359150606085013567ffffffffffffffff81111561174957600080fd5b8501601f8101871361175a57600080fd5b61176987823560208401611589565b91505092959194509250565b60008060006060848603121561178a57600080fd5b6117938461152d565b925060208401359150604084013567ffffffffffffffff8111156117b657600080fd5b6117c2868287016115ff565b9150509250925092565b600080604083850312156117df57600080fd5b6117e88361152d565b91506117f66020840161152d565b90509250929050565b600181811c9082168061181357607f821691505b60208210810361183357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f8211156105e6576000816000526020600020601f850160051c810160208610156118785750805b601f850160051c820191505b8181101561189757828155600101611884565b505050505050565b815167ffffffffffffffff8111156118b9576118b9611573565b6118cd816118c784546117ff565b8461184f565b602080601f83116001811461190257600084156118ea5750858301515b600019600386901b1c1916600185901b178555611897565b600085815260208120601f198616915b8281101561193157888601518255948401946001909101908401611912565b508582101561194f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611992908301846114d5565b9695505050505050565b6000602082840312156119ae57600080fd5b8151610ef08161147e565b600083516119cb8184602088016114b1565b8351908301906119df8183602088016114b1565b01949350505050565b818103818111156103f457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212206ff38700c73b602455dbb7964f2d3281f62efc77263f0f3bdb67f5e4ee5d4f3f64736f6c63430008170033a26469706673582212207f55223fc039b168a1e0c0bb9dc8d219b8219d1b2151fe8e9843aecefd41f82664736f6c63430008170033" + +access(all) let bridgedNFTCodeChunks = [ + "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f7274204d6574616461746156696577732066726f6d203078303030303030303030303030303030310a696d706f727420566965775265736f6c7665722066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a696d706f72742045564d2066726f6d203078303030303030303030303030303030310a0a696d706f7274204943726f7373564d2066726f6d203078303030303030303030303030303030370a696d706f7274204945564d4272696467654e46544d696e7465722066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467654e4654457363726f772066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d427269646765436f6e6669672066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467655574696c732066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467652066726f6d203078303030303030303030303030303030370a696d706f72742043726f7373564d4e46542066726f6d203078303030303030303030303030303030370a0a2f2f2f205468697320636f6e747261637420697320612074656d706c617465207573656420627920466c6f7745564d42726964676520746f20646566696e652045564d2d6e6174697665204e46547320627269646765642066726f6d20466c6f772045564d20746f20466c6f772e0a2f2f2f2055706f6e206465706c6f796d656e74206f66207468697320636f6e74726163742c2074686520636f6e7472616374206e616d65206973206465726976656420617320612066756e6374696f6e206f6620746865206173736574207479706520286865726520616e2045524337323120616b610a2f2f2f20616e204e46542920616e642074686520636f6e747261637427732045564d20616464726573732e20546865206465726976656420636f6e7472616374206e616d65206973207468656e206a6f696e65642077697468207468697320636f6e7472616374277320636f64652c0a2f2f2f207072657061726564206173206368756e6b7320696e20466c6f7745564d42726964676554656d706c61746573206265666f7265206265696e67206465706c6f79656420746f2074686520466c6f772045564d20427269646765206163636f756e742e0a2f2f2f0a2f2f2f204f6e206272696467696e672c2074686520455243373231206973207472616e7366657272656420746f2074686520627269646765277320436164656e63654f776e65644163636f756e742045564d206164647265737320616e642061206e6577204e4654206973206d696e7465642066726f6d0a2f2f2f207468697320636f6e747261637420746f20746865206272696467696e672063616c6c65722e204f6e2072657475726e20746f20466c6f772045564d2c2074686520726576657273652070726f6365737320697320666f6c6c6f776564202d2074686520746f6b656e206973206275726e65640a2f2f2f20696e207468697320636f6e747261637420616e642074686520455243373231206973207472616e7366657272656420746f2074686520646566696e656420726563697069656e742e20496e2074686973207761792c2074686520436164656e636520746f6b656e206163747320617320610a2f2f2f20726570726573656e746174696f6e206f6620626f7468207468652045564d204e465420616e642074687573206f776e6572736869702072696768747320746f2069742075706f6e206272696467696e67206261636b20746f20466c6f772045564d2e0a2f2f2f0a2f2f2f20546f20627269646765206265747765656e20564d732c20612063616c6c65722063616e20656974686572207573652074686520636f6e7472616374206d6574686f647320646566696e65642062656c6f772c206f72207573652074686520466c6f7745564d42726964676527730a2f2f2f206272696467696e67206d6574686f64732077686963682077696c6c2070726f6772616d61746963616c6c7920726f757465206272696467696e672063616c6c7320746f207468697320636f6e74726163742e0a2f2f2f0a2f2f20544f444f3a20496d706c656d656e74204e465420636f6e747261637420696e74657266616365206f6e636520763220617661696c61626c65206c6f63616c6c790a61636365737328616c6c2920636f6e747261637420", + "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20", + "2e7265736f6c7665436f6e747261637456696577280a2020202020202020202020202020202020202020202020207265736f75726365547970653a2073656c662e6765745479706528292c0a20202020202020202020202020202020202020202020202076696577547970653a20547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020202020202072657475726e20", + "2e7265736f6c7665436f6e747261637456696577280a2020202020202020202020202020202020202020202020207265736f75726365547970653a2073656c662e6765745479706528292c0a20202020202020202020202020202020202020202020202076696577547970653a20547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020202020202020202020290a2020202020202020202020207d0a20202020202020202020202072657475726e206e696c0a20202020202020207d0a0a20202020202020202f2f2f207075626c69632066756e6374696f6e207468617420616e796f6e652063616e2063616c6c20746f206372656174652061206e657720656d70747920636f6c6c656374696f6e0a202020202020202061636365737328616c6c292066756e20637265617465456d707479436f6c6c656374696f6e28293a20407b4e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e7d207b0a20202020202020202020202072657475726e203c2d20", + "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a2073656c662e676574547970652829290a20202020202020207d0a0a20202020202020202f2a202d2d2d2043726f7373564d4e465420636f6e666f726d616e6365202d2d2d202a2f0a20202020202020202f2f0a20202020202020202f2f2f2052657475726e73207468652045564d20636f6e74726163742061646472657373206f6620746865204e46540a202020202020202061636365737328616c6c2920766965772066756e2067657445564d436f6e74726163744164647265737328293a2045564d2e45564d41646472657373207b0a20202020202020202020202072657475726e20", + "2e67657445564d436f6e74726163744164647265737328290a20202020202020207d0a0a20202020202020202f2f2f2053696d696c617220746f204552433732312e746f6b656e555249206d6574686f642c2072657475726e732074686520555249206f6620746865204e465420776974682073656c662e65766d49442061742074696d65206f66206272696467696e670a202020202020202061636365737328616c6c2920766965772066756e20746f6b656e55524928293a20537472696e67207b0a20202020202020202020202072657475726e20", + "2e746f6b656e555249735b73656c662e65766d49445d203f3f2022220a20202020202020207d0a202020207d0a0a202020202f2f2f2054686973207265736f7572636520686f6c6473206173736f636961746564204e4654732c20616e642073657276657320717565726965732061626f75742073746f726564204e4654730a2020202061636365737328616c6c29207265736f7572636520436f6c6c656374696f6e3a204e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e2c2043726f7373564d4e46542e45564d4e4654436f6c6c656374696f6e207b0a20202020202020202f2f2f2064696374696f6e617279206f66204e465420636f6e666f726d696e6720746f6b656e7320696e6465786564206f6e2074686569722049440a202020202020202061636365737328636f6e74726163742920766172206f776e65644e4654733a20407b55496e7436343a20", + "2e4e46547d0a20202020202020202f2f2f204d617070696e67206f662045564d2049447320746f20466c6f77204e4654204944730a202020202020202061636365737328636f6e747261637429206c65742065766d4944546f466c6f7749443a207b55496e743235363a2055496e7436347d0a0a202020202020202061636365737328616c6c29207661722073746f72616765506174683a2053746f72616765506174680a202020202020202061636365737328616c6c2920766172207075626c6963506174683a205075626c6963506174680a0a2020202020202020696e6974202829207b0a20202020202020202020202073656c662e6f776e65644e465473203c2d207b7d0a20202020202020202020202073656c662e65766d4944546f466c6f774944203d207b7d0a2020202020202020202020206c657420636f6c6c656374696f6e44617461203d20", + "2e7265736f6c7665436f6e747261637456696577280a20202020202020202020202020202020202020207265736f75726365547970653a20547970653c40", + "2e4e46543e28292c0a202020202020202020202020202020202020202076696577547970653a20547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28290a202020202020202020202020202020202920617321204d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613f0a202020202020202020202020202020203f3f2070616e69632822436f756c64206e6f74207265736f6c76652074686520636f6c6c656374696f6e2064617461207669657720666f7220746865204e465420636f6c6c656374696f6e22290a20202020202020202020202073656c662e73746f7261676550617468203d20636f6c6c656374696f6e446174612e73746f72616765506174680a20202020202020202020202073656c662e7075626c696350617468203d20636f6c6c656374696f6e446174612e7075626c6963506174680a20202020202020207d0a0a20202020202020202f2f2f2052657475726e732061206c697374206f66204e46542074797065732074686174207468697320726563656976657220616363657074730a202020202020202061636365737328616c6c2920766965772066756e20676574537570706f727465644e4654547970657328293a207b547970653a20426f6f6c7d207b0a20202020202020202020202072657475726e207b20547970653c40", + "2e4e46543e28293a2074727565207d0a20202020202020207d0a0a20202020202020202f2f2f2052657475726e732077686574686572206f72206e6f742074686520676976656e20747970652069732061636365707465642062792074686520636f6c6c656374696f6e0a20202020202020202f2f2f204120636f6c6c656374696f6e20746861742063616e2061636365707420616e7920747970652073686f756c64206a7573742072657475726e20747275652062792064656661756c740a202020202020202061636365737328616c6c2920766965772066756e206973537570706f727465644e46545479706528747970653a2054797065293a20426f6f6c207b0a202020202020202020202072657475726e2074797065203d3d20547970653c40", + "2e4e46543e28290a20202020202020207d0a0a20202020202020202f2f2f2052656d6f76657320616e204e46542066726f6d2074686520636f6c6c656374696f6e20616e64206d6f76657320697420746f207468652063616c6c65720a2020202020202020616363657373284e6f6e46756e6769626c65546f6b656e2e5769746864726177207c204e6f6e46756e6769626c65546f6b656e2e4f776e6572292066756e20776974686472617728776974686472617749443a2055496e743634293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a2020202020202020202020206c657420746f6b656e203c2d2073656c662e6f776e65644e4654732e72656d6f7665286b65793a2077697468647261774944290a202020202020202020202020202020203f3f2070616e69632822436f756c64206e6f7420776974686472617720616e204e46542077697468207468652070726f76696465642049442066726f6d2074686520636f6c6c656374696f6e22290a0a20202020202020202020202072657475726e203c2d746f6b656e0a20202020202020207d0a0a20202020202020202f2f2f2057697468647261777320616e204e46542066726f6d2074686520636f6c6c656374696f6e206279206974732045564d2049440a2020202020202020616363657373284e6f6e46756e6769626c65546f6b656e2e5769746864726177207c204e6f6e46756e6769626c65546f6b656e2e4f776e6572292066756e207769746864726177427945564d4944285f2069643a2055496e743634293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a2020202020202020202020206c657420746f6b656e203c2d2073656c662e6f776e65644e4654732e72656d6f7665286b65793a206964290a202020202020202020202020202020203f3f2070616e69632822436f756c64206e6f7420776974686472617720616e204e46542077697468207468652070726f76696465642049442066726f6d2074686520636f6c6c656374696f6e22290a0a20202020202020202020202072657475726e203c2d746f6b656e0a20202020202020207d0a0a20202020202020202f2f2f205474616b65732061204e465420616e64206164647320697420746f2074686520636f6c6c656374696f6e732064696374696f6e61727920616e6420616464732074686520494420746f207468652065766d4944546f466c6f774944206d617070696e670a202020202020202061636365737328616c6c292066756e206465706f73697428746f6b656e3a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d29207b0a2020202020202020202020206c657420746f6b656e203c2d20746f6b656e206173212040", + "2e4e46540a0a2020202020202020202020202f2f2061646420746865206e657720746f6b656e20746f207468652064696374696f6e6172792077686963682072656d6f76657320746865206f6c64206f6e650a20202020202020202020202073656c662e65766d4944546f466c6f7749445b746f6b656e2e65766d49445d203d20746f6b656e2e69640a2020202020202020202020206c6574206f6c64546f6b656e203c2d2073656c662e6f776e65644e4654735b746f6b656e2e69645d203c2d20746f6b656e0a0a20202020202020202020202064657374726f79206f6c64546f6b656e0a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320616e206172726179206f66207468652049447320746861742061726520696e2074686520636f6c6c656374696f6e0a202020202020202061636365737328616c6c2920766965772066756e2067657449447328293a205b55496e7436345d207b0a20202020202020202020202072657475726e2073656c662e6f776e65644e4654732e6b6579730a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320616e206172726179206f66207468652045564d2049447320746861742061726520696e2074686520636f6c6c656374696f6e0a202020202020202061636365737328616c6c2920766965772066756e2067657445564d49447328293a205b55496e743235365d207b0a20202020202020202020202072657475726e2073656c662e65766d4944546f466c6f7749442e6b6579730a20202020202020207d0a0a20202020202020202f2f2f2052657475726e732074686520436164656e6365204e46542e696420666f722074686520676976656e2045564d204e46542049442069660a202020202020202061636365737328616c6c2920766965772066756e20676574436164656e636549442866726f6d2065766d49443a2055496e74323536293a2055496e7436343f207b0a20202020202020202020202072657475726e2073656c662e65766d4944546f466c6f7749445b65766d49445d203f3f2055496e7436342865766d4944290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e73207468652045564d204e4654204944206173736f63696174656420776974682074686520436164656e6365204e46542049442e2054686520676f616c20697320746f20726574726965766520746865204552433732312049442076616c75652e0a20202020202020202f2f2f20417320666172206173207468652062726964676520697320636f6e6365726e65642c20616e2045524337323120646566696e6564206279207468652062726964676520697320746865204e46542773204944206174207468652074696d65206f66206272696467696e670a20202020202020202f2f2f206f72207468652076616c7565206f6620746865204e46542e65766d494420696620697420696d706c656d656e7473207468652043726f7373564d4e46542e45564d4e465420696e74657266616365207768656e20627269646765642e0a20202020202020202f2f2f20466f6c6c6f77696e672074686973207061747465726e2c206966206c6f636b65642c20746865204e465420697320636865636b656420666f722045564d4e465420636f6e666f726d616e63652072657475726e696e67202e65766d494420696620736f2c0a20202020202020202f2f2f206f746865727769736520746865204e465427732049442069732072657475726e656420617320612055496e743235362073696e63652074686174277320686f77207468652062726964676520776f756c642068616e646c65206d696e74696e6720696e207468650a20202020202020202f2f2f20636f72726573706f6e64696e672045524337323120636f6e74726163742e0a20202020202020202f2f2f0a202020202020202061636365737328616c6c2920766965772066756e2067657445564d49442866726f6d20636164656e636549443a2055496e743634293a2055496e743235363f207b0a2020202020202020202020206966206c6574206e6674203d2073656c662e626f72726f774e465428636164656e6365494429207b0a202020202020202020202020202020206966206c65742065766d4e4654203d2043726f7373564d4e46542e67657445564d49442866726f6d3a206e667429207b0a202020202020202020202020202020202020202072657475726e2065766d4e46540a202020202020202020202020202020207d0a2020202020202020202020202020202072657475726e2055496e74323536286e66742e6964290a2020202020202020202020207d0a20202020202020202020202072657475726e206e696c0a20202020202020207d0a0a20202020202020202f2f2f2052657475726e732074686520636f6e747261637455524920666f7220746865204e465420636f6c6c656374696f6e20617320646566696e656420696e2074686520736f757263652045524337323120636f6e74726163742e204966206e6f6e65207761730a20202020202020202f2f2f20646566696e6564206174207468652074696d65206f66206272696467696e672c20616e20656d70747920737472696e672069732072657475726e65642e0a202020202020202061636365737328616c6c2920766965772066756e20636f6e747261637455524928293a20537472696e673f207b0a20202020202020202020202072657475726e20", + "2e636f6e74726163745552490a20202020202020207d0a0a20202020202020202f2f2f20476574732074686520616d6f756e74206f66204e4654732073746f72656420696e2074686520636f6c6c656374696f6e0a202020202020202061636365737328616c6c2920766965772066756e206765744c656e67746828293a20496e74207b0a20202020202020202020202072657475726e2073656c662e6f776e65644e4654732e6b6579732e6c656e6774680a20202020202020207d0a0a20202020202020202f2f2f205265747269657665732061207265666572656e636520746f20746865204e46542073746f72656420696e2074686520636f6c6c656374696f6e206279206974732049440a202020202020202061636365737328616c6c2920766965772066756e20626f72726f774e4654285f2069643a2055496e743634293a20267b4e6f6e46756e6769626c65546f6b656e2e4e46547d3f207b0a20202020202020202020202072657475726e202673656c662e6f776e65644e4654735b69645d0a20202020202020207d0a0a20202020202020202f2f2f20426f72726f77207468652076696577207265736f6c76657220666f722074686520737065636966696564204e46542049440a202020202020202061636365737328616c6c2920766965772066756e20626f72726f77566965775265736f6c7665722869643a2055496e743634293a20267b566965775265736f6c7665722e5265736f6c7665727d3f207b0a2020202020202020202020206966206c6574206e6674203d202673656c662e6f776e65644e4654735b69645d2061732026", + "2e4e46543f207b0a2020202020202020202020202020202072657475726e206e667420617320267b566965775265736f6c7665722e5265736f6c7665727d0a2020202020202020202020207d0a20202020202020202020202072657475726e206e696c0a20202020202020207d0a0a20202020202020202f2f2f204372656174657320616e20656d70747920636f6c6c656374696f6e0a202020202020202061636365737328616c6c292066756e20637265617465456d707479436f6c6c656374696f6e28293a20407b4e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e7d20207b0a20202020202020202020202072657475726e203c2d", + "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a20547970653c40", + "2e4e46543e2829290a20202020202020207d0a202020207d0a0a202020202f2f2f20637265617465456d707479436f6c6c656374696f6e206372656174657320616e20656d70747920436f6c6c656374696f6e20666f722074686520737065636966696564204e465420747970650a202020202f2f2f20616e642072657475726e7320697420746f207468652063616c6c657220736f207468617420746865792063616e206f776e204e4654730a2020202061636365737328616c6c292066756e20637265617465456d707479436f6c6c656374696f6e286e6674547970653a2054797065293a20407b4e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e7d207b0a202020202020202072657475726e203c2d2063726561746520436f6c6c656374696f6e28290a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a202020202020202020202020476574746572730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f2052657475726e73207468652045564d20636f6e74726163742061646472657373206f6620746865204e4654207468697320636f6e747261637420726570726573656e74730a202020202f2f2f0a2020202061636365737328616c6c2920766965772066756e2067657445564d436f6e74726163744164647265737328293a2045564d2e45564d41646472657373207b0a202020202020202072657475726e2073656c662e65766d4e4654436f6e7472616374416464726573730a202020207d0a0a202020202f2f2f2046756e6374696f6e20746861742072657475726e7320616c6c20746865204d6574616461746120566965777320696d706c656d656e7465642062792061204e6f6e2046756e6769626c6520546f6b656e0a202020202f2f2f0a202020202f2f2f204072657475726e20416e206172726179206f6620547970657320646566696e696e672074686520696d706c656d656e7465642076696577732e20546869732076616c75652077696c6c20626520757365642062790a202020202f2f2f202020202020202020646576656c6f7065727320746f206b6e6f7720776869636820706172616d6574657220746f207061737320746f20746865207265736f6c7665566965772829206d6574686f642e0a202020202f2f2f0a2020202061636365737328616c6c2920766965772066756e20676574436f6e74726163745669657773287265736f75726365547970653a20547970653f293a205b547970655d207b0a202020202020202072657475726e205b0a202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28292c0a202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28290a20202020202020205d0a202020207d0a0a202020202f2f2f2046756e6374696f6e2074686174207265736f6c7665732061206d65746164617461207669657720666f72207468697320636f6e74726163742e0a202020202f2f2f0a202020202f2f2f2040706172616d20766965773a205468652054797065206f6620746865206465736972656420766965772e0a202020202f2f2f204072657475726e20412073747275637475726520726570726573656e74696e67207468652072657175657374656420766965772e0a202020202f2f2f0a2020202061636365737328616c6c292066756e207265736f6c7665436f6e747261637456696577287265736f75726365547970653a20547970653f2c2076696577547970653a2054797065293a20416e795374727563743f207b0a2020202020202020737769746368207669657754797065207b0a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020206c6574206964656e746966696572203d2022", + "436f6c6c656374696f6e220a202020202020202020202020202020206c657420636f6c6c656374696f6e44617461203d204d6574616461746156696577732e4e4654436f6c6c656374696f6e44617461280a202020202020202020202020202020202020202073746f72616765506174683a2053746f7261676550617468286964656e7469666965723a206964656e74696669657229212c0a20202020202020202020202020202020202020207075626c6963506174683a205075626c696350617468286964656e7469666965723a206964656e74696669657229212c0a20202020202020202020202020202020202020207075626c6963436f6c6c656374696f6e3a20547970653c26", + "2e436f6c6c656374696f6e3e28292c0a20202020202020202020202020202020202020207075626c69634c696e6b6564547970653a20547970653c26", + "2e436f6c6c656374696f6e3e28292c0a2020202020202020202020202020202020202020637265617465456d707479436f6c6c656374696f6e46756e6374696f6e3a202866756e28293a20407b4e6f6e46756e6769626c65546f6b656e2e436f6c6c656374696f6e7d207b0a20202020202020202020202020202020202020202020202072657475726e203c2d", + "2e637265617465456d707479436f6c6c656374696f6e286e6674547970653a20547970653c40", + "2e4e46543e2829290a20202020202020202020202020202020202020207d290a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e20636f6c6c656374696f6e446174610a2020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28293a0a202020202020202020202020202020206c6574206d65646961203d204d6574616461746156696577732e4d65646961280a202020202020202020202020202020202020202066696c653a204d6574616461746156696577732e4854545046696c65280a20202020202020202020202020202020202020202020202075726c3a202268747470733a2f2f6173736574732e776562736974652d66696c65732e636f6d2f3566363239346330633761386364643634336231633832302f3566363239346330633761386364613535636231633933365f466c6f775f576f72646d61726b2e737667220a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206d65646961547970653a2022696d6167652f7376672b786d6c220a20202020202020202020202020202020290a2020202020202020202020202020202072657475726e204d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c6179280a20202020202020202020202020202020202020206e616d653a202254686520466c6f77564d2042726964676564204e465420436f6c6c656374696f6e222c0a20202020202020202020202020202020202020206465736372697074696f6e3a20225468697320636f6c6c656374696f6e2077617320627269646765642066726f6d20466c6f772045564d2e222c0a202020202020202020202020202020202020202065787465726e616c55524c3a204d6574616461746156696577732e45787465726e616c55524c282268747470733a2f2f6272696467652e666c6f772e636f6d2f6e667422292c0a2020202020202020202020202020202020202020737175617265496d6167653a206d656469612c0a202020202020202020202020202020202020202062616e6e6572496d6167653a206d656469612c0a2020202020202020202020202020202020202020736f6369616c733a207b7d0a20202020202020202020202020202020290a2020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a2020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a20202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202020202020202020207572693a2073656c662e636f6e747261637455524920213d206e696c203f2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e636f6e74726163745552492129203a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a202222290a20202020202020202020202020202020290a20202020202020207d0a202020202020202072657475726e206e696c0a202020207d0a0a202020202f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0a2020202020202020496e7465726e616c204d6574686f64730a202020202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2f0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f206d696e74204e4654732066726f6d206272696467652d646566696e6564204e465420636f6e7472616374730a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e206d696e744e46542869643a2055496e743235362c20746f6b656e5552493a20537472696e67293a20404e4654207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b69645d203d3d206e696c3a20224120746f6b656e20776974682074686520676976656e2045524337323120494420616c726561647920657869737473220a20202020202020207d0a202020202020202073656c662e746f6b656e555249735b69645d203d20746f6b656e5552490a202020202020202072657475726e203c2d637265617465204e4654280a2020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a20202020202020202020202065766d49443a2069642c0a2020202020202020202020206d657461646174613a207b0a20202020202020202020202020202020224272696467656420426c6f636b223a2067657443757272656e74426c6f636b28292e6865696768742c0a2020202020202020202020202020202022427269646765642054696d657374616d70223a2067657443757272656e74426c6f636b28292e74696d657374616d700a2020202020202020202020207d0a2020202020202020290a202020207d0a0a202020202f2f2f20416c6c6f7773207468652062726964676520746f207570646174652074686520555249206f662062726964676564204e4654732e205468697320617373756d65732074686174207468652045564d2d646566696e696e672070726f6a656374206d617920636f6e7461696e0a202020202f2f2f206c6f67696320286f6e636861696e206f72206f6666636861696e292077686963682075706461746573204e4654206d6574616461746120696e2074686520736f757263652045524337323120636f6e74726163742e204f6e206272696467696e672c20746865205552492063616e0a202020202f2f2f207468656e206265207570646174656420696e207468697320636f6e747261637420746f207265666c6563742074686520736f757263652045524337323120636f6e74726163742773206d657461646174612e0a202020202f2f2f0a20202020616363657373286163636f756e74290a2020202066756e20757064617465546f6b656e5552492865766d49443a2055496e743235362c206e65775552493a20537472696e6729207b0a2020202020202020707265207b0a20202020202020202020202073656c662e746f6b656e555249735b65766d49445d20213d206e696c3a20224e6f20746f6b656e20776974682074686520676976656e2045524337323120494420657869737473220a20202020202020207d0a202020202020202069662073656c662e746f6b656e555249735b65766d49445d20213d206e6577555249207b0a20202020202020202020202073656c662e746f6b656e555249735b65766d49445d203d206e65775552490a20202020202020207d0a202020207d0a0a20202020696e6974286e616d653a20537472696e672c2073796d626f6c3a20537472696e672c2065766d436f6e7472616374416464726573733a2045564d2e45564d416464726573732c20636f6e74726163745552493a20537472696e673f29207b0a202020202020202073656c662e65766d4e4654436f6e747261637441646472657373203d2065766d436f6e7472616374416464726573730a202020202020202073656c662e666c6f774e4654436f6e747261637441646472657373203d2073656c662e6163636f756e742e616464726573730a202020202020202073656c662e6e616d65203d206e616d650a202020202020202073656c662e73796d626f6c203d2073796d626f6c0a202020202020202073656c662e636f6e7472616374555249203d20636f6e74726163745552490a202020202020202073656c662e746f6b656e55524973203d207b7d0a202020202020202073656c662e636f6c6c656374696f6e203c2d2063726561746520436f6c6c656374696f6e28290a0a2020202020202020466c6f7745564d427269646765436f6e6669672e6173736f63696174655479706528547970653c40", + "2e4e46543e28292c20776974683a2073656c662e65766d4e4654436f6e747261637441646472657373290a2020202020202020466c6f7745564d4272696467654e4654457363726f772e696e697469616c697a65457363726f77280a202020202020202020202020666f72547970653a20547970653c40", + "2e4e46543e28292c0a202020202020202020202020657263373231416464726573733a2073656c662e65766d4e4654436f6e7472616374416464726573730a2020202020202020290a202020207d0a7d0a" +] + +access(all) +fun getEVMUpdateCode(): String { + return evmUpdateCode +} + +access(all) +fun getCompiledFactoryBytecode(): String { + return compiledFactoryBytecode +} + +access(all) +fun getBridgedNFTCodeChunks(): [String] { + return bridgedNFTCodeChunks +} \ No newline at end of file From f50149ffcc1b80b02b61241fb5d5ae58ce4200b9 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:33:31 -0500 Subject: [PATCH 32/39] update setup scripts --- local/setup_emulator.1.sh | 26 +++++++++++++++++++++----- local/setup_emulator.2.sh | 20 -------------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/local/setup_emulator.1.sh b/local/setup_emulator.1.sh index 20641e18..2cabd11c 100644 --- a/local/setup_emulator.1.sh +++ b/local/setup_emulator.1.sh @@ -10,12 +10,28 @@ flow accounts update-contract ./cadence/contracts/standards/EVM.cdc # Create COA in emulator-account -# Deploy the Factory contract - NOTE THE `deployedContractAddress` IN THE EMITTED EVENT -flow transactions send ./cadence/transactions/evm/deploy.cdc \ - --args-json "$(cat ./cadence/args/deploy-factory-args.json)" - # Deploy initial bridge contracts flow accounts add-contract ./cadence/contracts/bridge/BridgePermissions.cdc flow accounts add-contract ./cadence/contracts/bridge/ICrossVM.cdc flow accounts add-contract ./cadence/contracts/bridge/CrossVMNFT.cdc -flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc \ No newline at end of file +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc + + +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \ + --args-json "$(cat ./cadence/args/deploy-factory-args.json)" + +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc +# Add the templated contract code chunks for FlowEVMBridgedNFTTemplate.cdc contents +flow transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \ + --args-json "$(cat ./cadence/args/bridged-nft-code-chunks-args.json)" --gas-limit 1600 + +flow accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc + +# Deploy Serialization Utils +flow accounts add-contract ./cadence/contracts/utils/Serialize.cdc +flow accounts add-contract ./cadence/contracts/utils/SerializeNFT.cdc + +# Deploy main bridge interface & contract +flow accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc +flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc \ No newline at end of file diff --git a/local/setup_emulator.2.sh b/local/setup_emulator.2.sh index 4143ef95..3d041cdd 100644 --- a/local/setup_emulator.2.sh +++ b/local/setup_emulator.2.sh @@ -1,23 +1,3 @@ -# Provided address is the address of the Factory contract deployed in the previous txn -flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \ - - -flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc -flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc -# Add the templated contract code chunks for FlowEVMBridgedNFTTemplate.cdc contents -flow transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \ - --args-json "$(cat ./cadence/args/bridged-nft-code-chunks-args.json)" --gas-limit 1600 - -flow accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc - -# Deploy Serialization Utils -flow accounts add-contract ./cadence/contracts/utils/Serialize.cdc -flow accounts add-contract ./cadence/contracts/utils/SerializeNFT.cdc - -# Deploy main bridge interface & contract -flow accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc -flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc - # Deploy the bridge router directing calls from COAs to the dedicated bridge flow accounts add-contract ./cadence/contracts/bridge/EVMBridgeRouter.cdc 0xf8d6e0586b0a20c7 FlowEVMBridge From e63b1ad88546f6a63d8f8a14931c4477b1d65a93 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:33:56 -0500 Subject: [PATCH 33/39] add update_contract test txn --- cadence/transactions/test/update_contract.cdc | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cadence/transactions/test/update_contract.cdc diff --git a/cadence/transactions/test/update_contract.cdc b/cadence/transactions/test/update_contract.cdc new file mode 100644 index 00000000..7f2ceb85 --- /dev/null +++ b/cadence/transactions/test/update_contract.cdc @@ -0,0 +1,5 @@ +transaction(name: String, codeHex: String) { + prepare(signer: auth(UpdateContract) &Account) { + signer.contracts.update(name: name, code: codeHex.decodeHex()) + } +} \ No newline at end of file From 343925ebfb1db945ba3718fe5516836163381e36 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:19:36 -0500 Subject: [PATCH 34/39] add further test coverage --- .../testing/EVMBridgedNFTTemplate.cdc | 381 ++++++++++++++++++ cadence/contracts/test/EVMDeployer.cdc | 20 + .../get_deployed_erc721_address_string.cdc | 10 + cadence/tests/flow_evm_bridge_tests.cdc | 53 ++- cadence/tests/test_helpers.cdc | 7 + .../example-assets/safe_mint_erc721.cdc | 6 +- flow.json | 7 + 7 files changed, 480 insertions(+), 4 deletions(-) create mode 100644 cadence/contracts/templates/testing/EVMBridgedNFTTemplate.cdc create mode 100644 cadence/contracts/test/EVMDeployer.cdc create mode 100644 cadence/scripts/test/get_deployed_erc721_address_string.cdc diff --git a/cadence/contracts/templates/testing/EVMBridgedNFTTemplate.cdc b/cadence/contracts/templates/testing/EVMBridgedNFTTemplate.cdc new file mode 100644 index 00000000..c46fae2f --- /dev/null +++ b/cadence/contracts/templates/testing/EVMBridgedNFTTemplate.cdc @@ -0,0 +1,381 @@ +import NonFungibleToken from 0x0000000000000001 +import MetadataViews from 0x0000000000000001 +import ViewResolver from 0x0000000000000001 +import FungibleToken from 0x0000000000000002 +import FlowToken from 0x0000000000000003 + +import EVM from 0x0000000000000001 + +import ICrossVM from 0x0000000000000007 +import IEVMBridgeNFTMinter from 0x0000000000000007 +import FlowEVMBridgeNFTEscrow from 0x0000000000000007 +import FlowEVMBridgeConfig from 0x0000000000000007 +import FlowEVMBridgeUtils from 0x0000000000000007 +import FlowEVMBridge from 0x0000000000000007 +import CrossVMNFT from 0x0000000000000007 + +/// This contract is a template used by FlowEVMBridge to define EVM-native NFTs bridged from Flow EVM to Flow. +/// Upon deployment of this contract, the contract name is derived as a function of the asset type (here an ERC721 aka +/// an NFT) and the contract's EVM address. The derived contract name is then joined with this contract's code, +/// prepared as chunks in FlowEVMBridgeTemplates before being deployed to the Flow EVM Bridge account. +/// +/// On bridging, the ERC721 is transferred to the bridge's CadenceOwnedAccount EVM address and a new NFT is minted from +/// this contract to the bridging caller. On return to Flow EVM, the reverse process is followed - the token is burned +/// in this contract and the ERC721 is transferred to the defined recipient. In this way, the Cadence token acts as a +/// representation of both the EVM NFT and thus ownership rights to it upon bridging back to Flow EVM. +/// +/// To bridge between VMs, a caller can either use the contract methods defined below, or use the FlowEVMBridge's +/// bridging methods which will programatically route bridging calls to this contract. +/// +// TODO: Implement NFT contract interface once v2 available locally +access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungibleToken { + + /// Pointer to the Factory deployed Solidity contract address defining the bridged asset + access(all) let evmNFTContractAddress: EVM.EVMAddress + /// Pointer to the Flow NFT contract address defining the bridged asset, this contract address in this case + access(all) let flowNFTContractAddress: Address + /// Name of the NFT collection defined in the corresponding ERC721 contract + access(all) let name: String + /// Symbol of the NFT collection defined in the corresponding ERC721 contract + access(all) let symbol: String + /// URI of the contract, if available as a var in case the bridge enables cross-VM Metadata syncing in the future + access(all) var contractURI: String? + /// Retain a Collection to reference when resolving Collection Metadata + access(self) let collection: @Collection + /// Mapping of token URIs indexed on their ERC721 ID. This would not normally be retained within a Cadence NFT + /// contract, but since NFT metadata may be updated in EVM, it's retained here so that the bridge can update + /// it against the source ERC721 contract which is treated as the NFT's source of truth. + access(all) let tokenURIs: {UInt256: String} + + /// The NFT resource representing the bridged ERC721 token + /// + access(all) resource NFT: CrossVMNFT.EVMNFT { + /// The Cadence ID of the NFT + access(all) let id: UInt64 + /// The ERC721 ID of the NFT + access(all) let evmID: UInt256 + /// The name of the NFT as defined in the ERC721 contract + access(all) let name: String + /// The symbol of the NFT as defined in the ERC721 contract + access(all) let symbol: String + /// Additional onchain metadata + access(all) let metadata: {String: AnyStruct} + + init( + name: String, + symbol: String, + evmID: UInt256, + metadata: {String: AnyStruct} + ) { + self.name = name + self.symbol = symbol + self.id = self.uuid + self.evmID = evmID + self.metadata = metadata + } + + /// Returns the metadata view types supported by this NFT + access(all) view fun getViews(): [Type] { + return [ + Type(), + Type(), + Type(), + Type() + ] + } + + /// Resolves a metadata view for this NFT + access(all) fun resolveView(_ view: Type): AnyStruct? { + switch view { + // We don't know what kind of file the URI represents (IPFS v HTTP), so we can't resolve Display view + // with the URI as thumbnail - we may a new standard view for EVM NFTs - this is interim + case Type(): + return CrossVMNFT.EVMBridgedMetadata( + name: self.name, + symbol: self.symbol, + uri: CrossVMNFT.URI(baseURI: nil, value: self.tokenURI()) + ) + case Type(): + return MetadataViews.Serial( + self.id + ) + case Type(): + return {{CONTRACT_NAME}}.resolveContractView( + resourceType: self.getType(), + viewType: Type() + ) + case Type(): + return {{CONTRACT_NAME}}.resolveContractView( + resourceType: self.getType(), + viewType: Type() + ) + } + return nil + } + + /// public function that anyone can call to create a new empty collection + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <- {{CONTRACT_NAME}}.createEmptyCollection(nftType: self.getType()) + } + + /* --- CrossVMNFT conformance --- */ + // + /// Returns the EVM contract address of the NFT + access(all) view fun getEVMContractAddress(): EVM.EVMAddress { + return {{CONTRACT_NAME}}.getEVMContractAddress() + } + + /// Similar to ERC721.tokenURI method, returns the URI of the NFT with self.evmID at time of bridging + access(all) view fun tokenURI(): String { + return {{CONTRACT_NAME}}.tokenURIs[self.evmID] ?? "" + } + } + + /// This resource holds associated NFTs, and serves queries about stored NFTs + access(all) resource Collection: NonFungibleToken.Collection, CrossVMNFT.EVMNFTCollection { + /// dictionary of NFT conforming tokens indexed on their ID + access(contract) var ownedNFTs: @{UInt64: {{CONTRACT_NAME}}.NFT} + /// Mapping of EVM IDs to Flow NFT IDs + access(contract) let evmIDToFlowID: {UInt256: UInt64} + + access(all) var storagePath: StoragePath + access(all) var publicPath: PublicPath + + init () { + self.ownedNFTs <- {} + self.evmIDToFlowID = {} + let collectionData = {{CONTRACT_NAME}}.resolveContractView( + resourceType: Type<@{{CONTRACT_NAME}}.NFT>(), + viewType: Type() + ) as! MetadataViews.NFTCollectionData? + ?? panic("Could not resolve the collection data view for the NFT collection") + self.storagePath = collectionData.storagePath + self.publicPath = collectionData.publicPath + } + + /// Returns a list of NFT types that this receiver accepts + access(all) view fun getSupportedNFTTypes(): {Type: Bool} { + return { Type<@{{CONTRACT_NAME}}.NFT>(): true } + } + + /// Returns whether or not the given type is accepted by the collection + /// A collection that can accept any type should just return true by default + access(all) view fun isSupportedNFTType(type: Type): Bool { + return type == Type<@{{CONTRACT_NAME}}.NFT>() + } + + /// Removes an NFT from the collection and moves it to the caller + access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} { + let token <- self.ownedNFTs.remove(key: withdrawID) + ?? panic("Could not withdraw an NFT with the provided ID from the collection") + + return <-token + } + + /// Withdraws an NFT from the collection by its EVM ID + access(NonFungibleToken.Withdraw | NonFungibleToken.Owner) fun withdrawByEVMID(_ id: UInt64): @{NonFungibleToken.NFT} { + let token <- self.ownedNFTs.remove(key: id) + ?? panic("Could not withdraw an NFT with the provided ID from the collection") + + return <-token + } + + /// Ttakes a NFT and adds it to the collections dictionary and adds the ID to the evmIDToFlowID mapping + access(all) fun deposit(token: @{NonFungibleToken.NFT}) { + let token <- token as! @{{CONTRACT_NAME}}.NFT + + // add the new token to the dictionary which removes the old one + self.evmIDToFlowID[token.evmID] = token.id + let oldToken <- self.ownedNFTs[token.id] <- token + + destroy oldToken + } + + /// Returns an array of the IDs that are in the collection + access(all) view fun getIDs(): [UInt64] { + return self.ownedNFTs.keys + } + + /// Returns an array of the EVM IDs that are in the collection + access(all) view fun getEVMIDs(): [UInt256] { + return self.evmIDToFlowID.keys + } + + /// Returns the Cadence NFT.id for the given EVM NFT ID if + access(all) view fun getCadenceID(from evmID: UInt256): UInt64? { + return self.evmIDToFlowID[evmID] ?? UInt64(evmID) + } + + /// Returns the EVM NFT ID associated with the Cadence NFT ID. The goal is to retrieve the ERC721 ID value. + /// As far as the bridge is concerned, an ERC721 defined by the bridge is the NFT's ID at the time of bridging + /// or the value of the NFT.evmID if it implements the CrossVMNFT.EVMNFT interface when bridged. + /// Following this pattern, if locked, the NFT is checked for EVMNFT conformance returning .evmID if so, + /// otherwise the NFT's ID is returned as a UInt256 since that's how the bridge would handle minting in the + /// corresponding ERC721 contract. + /// + access(all) view fun getEVMID(from cadenceID: UInt64): UInt256? { + if let nft = self.borrowNFT(cadenceID) { + if let evmNFT = CrossVMNFT.getEVMID(from: nft) { + return evmNFT + } + return UInt256(nft.id) + } + return nil + } + + /// Returns the contractURI for the NFT collection as defined in the source ERC721 contract. If none was + /// defined at the time of bridging, an empty string is returned. + access(all) view fun contractURI(): String? { + return {{CONTRACT_NAME}}.contractURI + } + + /// Gets the amount of NFTs stored in the collection + access(all) view fun getLength(): Int { + return self.ownedNFTs.keys.length + } + + /// Retrieves a reference to the NFT stored in the collection by its ID + access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { + return &self.ownedNFTs[id] + } + + /// Borrow the view resolver for the specified NFT ID + access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? { + if let nft = &self.ownedNFTs[id] as &{{CONTRACT_NAME}}.NFT? { + return nft as &{ViewResolver.Resolver} + } + return nil + } + + /// Creates an empty collection + access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} { + return <-{{CONTRACT_NAME}}.createEmptyCollection(nftType: Type<@{{CONTRACT_NAME}}.NFT>()) + } + } + + /// createEmptyCollection creates an empty Collection for the specified NFT type + /// and returns it to the caller so that they can own NFTs + access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} { + return <- create Collection() + } + + /********************** + Getters + ***********************/ + + /// Returns the EVM contract address of the NFT this contract represents + /// + access(all) view fun getEVMContractAddress(): EVM.EVMAddress { + return self.evmNFTContractAddress + } + + /// Function that returns all the Metadata Views implemented by a Non Fungible Token + /// + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getContractViews(resourceType: Type?): [Type] { + return [ + Type(), + Type(), + Type() + ] + } + + /// Function that resolves a metadata view for this contract. + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? { + switch viewType { + case Type(): + let identifier = "{{CONTRACT_NAME}}Collection" + let collectionData = MetadataViews.NFTCollectionData( + storagePath: StoragePath(identifier: identifier)!, + publicPath: PublicPath(identifier: identifier)!, + publicCollection: Type<&{{CONTRACT_NAME}}.Collection>(), + publicLinkedType: Type<&{{CONTRACT_NAME}}.Collection>(), + createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} { + return <-{{CONTRACT_NAME}}.createEmptyCollection(nftType: Type<@{{CONTRACT_NAME}}.NFT>()) + }) + ) + return collectionData + case Type(): + let media = MetadataViews.Media( + file: MetadataViews.HTTPFile( + url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg" + ), + mediaType: "image/svg+xml" + ) + return MetadataViews.NFTCollectionDisplay( + name: "The FlowVM Bridged NFT Collection", + description: "This collection was bridged from Flow EVM.", + externalURL: MetadataViews.ExternalURL("https://bridge.flow.com/nft"), + squareImage: media, + bannerImage: media, + socials: {} + ) + case Type(): + return CrossVMNFT.EVMBridgedMetadata( + name: self.name, + symbol: self.symbol, + uri: self.contractURI != nil ? CrossVMNFT.URI(baseURI: nil, value: self.contractURI!) : CrossVMNFT.URI(baseURI: nil, value: "") + ) + } + return nil + } + + /********************** + Internal Methods + ***********************/ + + /// Allows the bridge to mint NFTs from bridge-defined NFT contracts + /// + access(account) + fun mintNFT(id: UInt256, tokenURI: String): @NFT { + pre { + self.tokenURIs[id] == nil: "A token with the given ERC721 ID already exists" + } + self.tokenURIs[id] = tokenURI + return <-create NFT( + name: self.name, + symbol: self.symbol, + evmID: id, + metadata: { + "Bridged Block": getCurrentBlock().height, + "Bridged Timestamp": getCurrentBlock().timestamp + } + ) + } + + /// Allows the bridge to update the URI of bridged NFTs. This assumes that the EVM-defining project may contain + /// logic (onchain or offchain) which updates NFT metadata in the source ERC721 contract. On bridging, the URI can + /// then be updated in this contract to reflect the source ERC721 contract's metadata. + /// + access(account) + fun updateTokenURI(evmID: UInt256, newURI: String) { + pre { + self.tokenURIs[evmID] != nil: "No token with the given ERC721 ID exists" + } + if self.tokenURIs[evmID] != newURI { + self.tokenURIs[evmID] = newURI + } + } + + init(name: String, symbol: String, evmContractAddress: EVM.EVMAddress, contractURI: String?) { + self.evmNFTContractAddress = evmContractAddress + self.flowNFTContractAddress = self.account.address + self.name = name + self.symbol = symbol + self.contractURI = contractURI + self.tokenURIs = {} + self.collection <- create Collection() + + FlowEVMBridgeConfig.associateType(Type<@{{CONTRACT_NAME}}.NFT>(), with: self.evmNFTContractAddress) + FlowEVMBridgeNFTEscrow.initializeEscrow( + forType: Type<@{{CONTRACT_NAME}}.NFT>(), + erc721Address: self.evmNFTContractAddress + ) + } +} diff --git a/cadence/contracts/test/EVMDeployer.cdc b/cadence/contracts/test/EVMDeployer.cdc new file mode 100644 index 00000000..9135f68f --- /dev/null +++ b/cadence/contracts/test/EVMDeployer.cdc @@ -0,0 +1,20 @@ +import "EVM" + +/// This contract is intended for testing purposes for the sake of capturing a deployed contract address while native +/// `evm.TransactionExecuted` event types are not available in Cadence testing framework. The deploying account should +/// already be configured with a `CadenceOwnedAccount` resource in storage at `/storage/evm`. +/// +access(all) contract EVMDeployer { + + access(all) let deployedAddress: EVM.EVMAddress + + init(bytecode: String, value: UInt) { + let coa = self.account.storage.borrow(from: /storage/evm) + ?? panic("No COA found in storage") + self.deployedAddress = coa.deploy( + code: bytecode.decodeHex(), + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: value) + ) + } +} \ No newline at end of file diff --git a/cadence/scripts/test/get_deployed_erc721_address_string.cdc b/cadence/scripts/test/get_deployed_erc721_address_string.cdc new file mode 100644 index 00000000..19830476 --- /dev/null +++ b/cadence/scripts/test/get_deployed_erc721_address_string.cdc @@ -0,0 +1,10 @@ +import "EVM" + +import "EVMDeployer" + +import "FlowEVMBridgeUtils" + +access(all) +fun main(): String { + return FlowEVMBridgeUtils.getEVMAddressAsHexString(address: EVMDeployer.deployedAddress) +} \ No newline at end of file diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index cf81ed07..387587cd 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -6,8 +6,10 @@ import "test_helpers.cdc" access(all) let serviceAccount = Test.serviceAccount() access(all) let bridgeAccount = Test.getAccount(0x0000000000000007) access(all) let exampleNFTAccount = Test.getAccount(0x0000000000000008) -access(all) let exampleERC721Account = Test.createAccount() +access(all) let exampleERC721Account = Test.getAccount(0x0000000000000009) access(all) let alice = Test.createAccount() +access(all) let erc721ID: UInt256 = 42 +access(all) let erc721URI = "ipfs://QmXf1Z6z5Y" access(all) fun setup() { @@ -139,6 +141,30 @@ fun setup() { arguments: [serviceAccount.address, "FlowEVMBridge"] ) Test.expect(err, Test.beNil()) + + // Transfer ERC721 deployer some $FLOW + let fundERC721AccountResult = executeTransaction( + "../transactions/flow-token/transfer_flow.cdc", + [exampleERC721Account.address, 100.0], + serviceAccount + ) + Test.expect(fundERC721AccountResult, Test.beSucceeded()) + // Configure bridge account with a COA + let createERC721COAResult = executeTransaction( + "../transactions/evm/create_account.cdc", + [10.0], + exampleERC721Account + ) + Test.expect(createERC721COAResult, Test.beSucceeded()) + // Deploy the ERC721 from EVMDeployer (simply to capture deploye EVM contract address) + // TODO: Replace this contract with the `deployedContractAddress` value emitted on deployment + // once `evm` events Types are available + err = Test.deployContract( + name: "EVMDeployer", + path: "../contracts/test/EVMDeployer.cdc", + arguments: [getCompiledERC721Bytecode(), UInt(0)] + ) + Test.expect(err, Test.beNil()) } access(all) @@ -165,3 +191,28 @@ fun testCreateCOASucceeds() { let stringAddress = coaAddressResult.returnValue as! String? Test.assertEqual(40, stringAddress!.length) } + +access(all) +fun testMintERC721Succeeds() { + let aliceCOAAddressResult = executeScript( + "../scripts/evm/get_evm_address_string.cdc", + [alice.address] + ) + Test.expect(aliceCOAAddressResult, Test.beSucceeded()) + let aliceCOAAddressString = aliceCOAAddressResult.returnValue as! String? ?? panic("Problem getting COA address as String") + Test.assertEqual(40, aliceCOAAddressString.length) + let erc721AddressResult = executeScript( + "../scripts/test/get_deployed_erc721_address_string.cdc", + [] + ) + Test.expect(erc721AddressResult, Test.beSucceeded()) + let erc721AddressString = erc721AddressResult.returnValue as! String? ?? panic("Problem getting COA address as String") + Test.assertEqual(40, erc721AddressString.length) + + let mintERC721Result = executeTransaction( + "../transactions/example-assets/safe_mint_erc721.cdc", + [aliceCOAAddressString, erc721ID, erc721URI, erc721AddressString, UInt64(150_000)], + exampleERC721Account + ) + Test.expect(mintERC721Result, Test.beSucceeded()) +} diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index 63516db9..e54bb5fd 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -2,6 +2,8 @@ access(all) let evmUpdateCode = "696d706f72742043727970746f0a0a696d706f7274204e6 access(all) let compiledFactoryBytecode = "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6129f4806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611eb78062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001eb738038062001eb7833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b50600c620000a0848262000386565b50600d620000af838262000386565b50600e620000be828262000386565b5050505050505062000452565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611a5580620004626000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a76b4d56116100a2578063cd279c7c11610071578063cd279c7c146103a8578063e8a3d485146103bb578063e985e9c5146103c3578063f2fde38b146103d657600080fd5b8063a76b4d5614610372578063b49bbd941461037a578063b88d4fde14610382578063c87b56dd1461039557600080fd5b806394e29329116100de57806394e293291461034757806395d89b411461034f578063a159047b14610357578063a22cb4651461035f57600080fd5b806370a082311461031b578063715018a61461032e5780638da5cb5b1461033657600080fd5b80632f745c59116101715780634f558e791161014b5780634f558e79146102c25780634f6ccce7146102ed5780635e0a9661146103005780636352211e1461030857600080fd5b80632f745c591461028957806342842e0e1461029c57806342966c68146102af57600080fd5b8063095ea7b3116101ad578063095ea7b31461023c57806318160ddd1461025157806318e97fd11461026357806323b872dd1461027657600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611494565b6103e9565b60405190151581526020015b60405180910390f35b6102046103fa565b6040516101f39190611501565b61022461021f366004611514565b61048c565b6040516001600160a01b0390911681526020016101f3565b61024f61024a366004611549565b6104b5565b005b6009545b6040519081526020016101f3565b61024f61027136600461161f565b6104c4565b61024f610284366004611666565b6104d6565b610255610297366004611549565b610566565b61024f6102aa366004611666565b6105cb565b61024f6102bd366004611514565b6105eb565b6101e76102d0366004611514565b6000908152600260205260409020546001600160a01b0316151590565b6102556102fb366004611514565b6105f7565b610204610650565b610224610316366004611514565b61065f565b6102556103293660046116a2565b61066a565b61024f6106b2565b600b546001600160a01b0316610224565b6102046106c6565b6102046106d5565b6102046106e4565b61024f61036d3660046116bd565b610772565b61020461077d565b61020461078a565b61024f6103903660046116f9565b610797565b6102046103a3366004611514565b6107ae565b61024f6103b6366004611775565b6107b9565b6102046107d5565b6101e76103d13660046117cc565b6107e4565b61024f6103e43660046116a2565b610812565b60006103f482610850565b92915050565b606060008054610409906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610435906117ff565b80156104825780601f1061045757610100808354040283529160200191610482565b820191906000526020600020905b81548152906001019060200180831161046557829003601f168201915b5050505050905090565b600061049782610875565b506000828152600460205260409020546001600160a01b03166103f4565b6104c08282336108ae565b5050565b6104cc6108bb565b6104c082826108e8565b6001600160a01b03821661050557604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610512838333610938565b9050836001600160a01b0316816001600160a01b031614610560576040516364283d7b60e01b81526001600160a01b03808616600483015260248201849052821660448201526064016104fc565b50505050565b60006105718361066a565b82106105a25760405163295f44f760e21b81526001600160a01b0384166004820152602481018390526044016104fc565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6105e683838360405180602001604052806000815250610797565b505050565b6104c060008233610938565b600061060260095490565b821061062b5760405163295f44f760e21b815260006004820152602481018390526044016104fc565b6009828154811061063e5761063e611839565b90600052602060002001549050919050565b6060600d8054610409906117ff565b60006103f482610875565b60006001600160a01b038216610696576040516322718ad960e21b8152600060048201526024016104fc565b506001600160a01b031660009081526003602052604090205490565b6106ba6108bb565b6106c4600061094d565b565b6060600c8054610409906117ff565b606060018054610409906117ff565b600d80546106f1906117ff565b80601f016020809104026020016040519081016040528092919081815260200182805461071d906117ff565b801561076a5780601f1061073f5761010080835404028352916020019161076a565b820191906000526020600020905b81548152906001019060200180831161074d57829003601f168201915b505050505081565b6104c033838361099f565b600e80546106f1906117ff565b600c80546106f1906117ff565b6107a28484846104d6565b61056084848484610a3e565b60606103f482610b67565b6107c16108bb565b6107cb8383610c70565b6105e682826108e8565b6060600e8054610409906117ff565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61081a6108bb565b6001600160a01b03811661084457604051631e4fbdf760e01b8152600060048201526024016104fc565b61084d8161094d565b50565b60006001600160e01b0319821663780e9d6360e01b14806103f457506103f482610c8a565b6000818152600260205260408120546001600160a01b0316806103f457604051637e27328960e01b8152600481018490526024016104fc565b6105e68383836001610caf565b600b546001600160a01b031633146106c45760405163118cdaa760e01b81523360048201526024016104fc565b6000828152600660205260409020610900828261189f565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6000610945848484610db5565b949350505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166109d157604051630b61174360e31b81526001600160a01b03831660048201526024016104fc565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561056057604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610a8090339088908790879060040161195f565b6020604051808303816000875af1925050508015610abb575060408051601f3d908101601f19168201909252610ab89181019061199c565b60015b610b24573d808015610ae9576040519150601f19603f3d011682016040523d82523d6000602084013e610aee565b606091505b508051600003610b1c57604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610b6057604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b5050505050565b6060610b7282610875565b5060008281526006602052604081208054610b8c906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb8906117ff565b8015610c055780601f10610bda57610100808354040283529160200191610c05565b820191906000526020600020905b815481529060010190602001808311610be857829003601f168201915b505050505090506000610c2360408051602081019091526000815290565b90508051600003610c35575092915050565b815115610c67578082604051602001610c4f9291906119b9565b60405160208183030381529060405292505050919050565b61094584610e82565b6104c0828260405180602001604052806000815250610ef7565b60006001600160e01b03198216632483248360e11b14806103f457506103f482610f0e565b8080610cc357506001600160a01b03821615155b15610d85576000610cd384610875565b90506001600160a01b03831615801590610cff5750826001600160a01b0316816001600160a01b031614155b8015610d125750610d1081846107e4565b155b15610d3b5760405163a9fbf51f60e01b81526001600160a01b03841660048201526024016104fc565b8115610d835783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610dc3858585610f5e565b90506001600160a01b038116610e2057610e1b84600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b610e43565b846001600160a01b0316816001600160a01b031614610e4357610e438185611057565b6001600160a01b038516610e5f57610e5a846110e8565b610945565b846001600160a01b0316816001600160a01b031614610945576109458585611197565b6060610e8d82610875565b506000610ea560408051602081019091526000815290565b90506000815111610ec55760405180602001604052806000815250610ef0565b80610ecf846111e7565b604051602001610ee09291906119b9565b6040516020818303038152906040525b9392505050565b610f01838361127a565b6105e66000848484610a3e565b60006001600160e01b031982166380ac58cd60e01b1480610f3f57506001600160e01b03198216635b5e139f60e01b145b806103f457506301ffc9a760e01b6001600160e01b03198316146103f4565b6000828152600260205260408120546001600160a01b0390811690831615610f8b57610f8b8184866112df565b6001600160a01b03811615610fc957610fa8600085600080610caf565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615610ff8576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006110628361066a565b6000838152600860205260409020549091508082146110b5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009546000906110fa906001906119e8565b6000838152600a60205260408120546009805493945090928490811061112257611122611839565b90600052602060002001549050806009838154811061114357611143611839565b6000918252602080832090910192909255828152600a9091526040808220849055858252812055600980548061117b5761117b611a09565b6001900381819060005260206000200160009055905550505050565b600060016111a48461066a565b6111ae91906119e8565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b606060006111f483611343565b600101905060008167ffffffffffffffff81111561121457611214611573565b6040519080825280601f01601f19166020018201604052801561123e576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461124857509392505050565b6001600160a01b0382166112a457604051633250574960e11b8152600060048201526024016104fc565b60006112b283836000610938565b90506001600160a01b038116156105e6576040516339e3563760e11b8152600060048201526024016104fc565b6112ea83838361141b565b6105e6576001600160a01b03831661131857604051637e27328960e01b8152600481018290526024016104fc565b60405163177e802f60e01b81526001600160a01b0383166004820152602481018290526044016104fc565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113825772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113ae576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113cc57662386f26fc10000830492506010015b6305f5e10083106113e4576305f5e100830492506008015b61271083106113f857612710830492506004015b6064831061140a576064830492506002015b600a83106103f45760010192915050565b60006001600160a01b038316158015906109455750826001600160a01b0316846001600160a01b03161480611455575061145584846107e4565b806109455750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461084d57600080fd5b6000602082840312156114a657600080fd5b8135610ef08161147e565b60005b838110156114cc5781810151838201526020016114b4565b50506000910152565b600081518084526114ed8160208601602086016114b1565b601f01601f19169290920160200192915050565b602081526000610ef060208301846114d5565b60006020828403121561152657600080fd5b5035919050565b80356001600160a01b038116811461154457600080fd5b919050565b6000806040838503121561155c57600080fd5b6115658361152d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156115a4576115a4611573565b604051601f8501601f19908116603f011681019082821181831017156115cc576115cc611573565b816040528093508581528686860111156115e557600080fd5b858560208301376000602087830101525050509392505050565b600082601f83011261161057600080fd5b610ef083833560208501611589565b6000806040838503121561163257600080fd5b82359150602083013567ffffffffffffffff81111561165057600080fd5b61165c858286016115ff565b9150509250929050565b60008060006060848603121561167b57600080fd5b6116848461152d565b92506116926020850161152d565b9150604084013590509250925092565b6000602082840312156116b457600080fd5b610ef08261152d565b600080604083850312156116d057600080fd5b6116d98361152d565b9150602083013580151581146116ee57600080fd5b809150509250929050565b6000806000806080858703121561170f57600080fd5b6117188561152d565b93506117266020860161152d565b925060408501359150606085013567ffffffffffffffff81111561174957600080fd5b8501601f8101871361175a57600080fd5b61176987823560208401611589565b91505092959194509250565b60008060006060848603121561178a57600080fd5b6117938461152d565b925060208401359150604084013567ffffffffffffffff8111156117b657600080fd5b6117c2868287016115ff565b9150509250925092565b600080604083850312156117df57600080fd5b6117e88361152d565b91506117f66020840161152d565b90509250929050565b600181811c9082168061181357607f821691505b60208210810361183357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f8211156105e6576000816000526020600020601f850160051c810160208610156118785750805b601f850160051c820191505b8181101561189757828155600101611884565b505050505050565b815167ffffffffffffffff8111156118b9576118b9611573565b6118cd816118c784546117ff565b8461184f565b602080601f83116001811461190257600084156118ea5750858301515b600019600386901b1c1916600185901b178555611897565b600085815260208120601f198616915b8281101561193157888601518255948401946001909101908401611912565b508582101561194f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611992908301846114d5565b9695505050505050565b6000602082840312156119ae57600080fd5b8151610ef08161147e565b600083516119cb8184602088016114b1565b8351908301906119df8183602088016114b1565b01949350505050565b818103818111156103f457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212206ff38700c73b602455dbb7964f2d3281f62efc77263f0f3bdb67f5e4ee5d4f3f64736f6c63430008170033a26469706673582212207f55223fc039b168a1e0c0bb9dc8d219b8219d1b2151fe8e9843aecefd41f82664736f6c63430008170033" +access(all) let compiledERC721Bytecode = "60806040523480156200001157600080fd5b5033604051806040016040528060048152602001634e414d4560e01b8152506040518060400160405280600681526020016514d6535093d360d21b8152508160009081620000609190620001ac565b5060016200006f8282620001ac565b5050506001600160a01b038116620000a157604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000ac81620000b3565b5062000278565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200013057607f821691505b6020821081036200015157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001a7576000816000526020600020601f850160051c81016020861015620001825750805b601f850160051c820191505b81811015620001a3578281556001016200018e565b5050505b505050565b81516001600160401b03811115620001c857620001c862000105565b620001e081620001d984546200011b565b8462000157565b602080601f831160018114620002185760008415620001ff5750858301515b600019600386901b1c1916600185901b178555620001a3565b600085815260208120601f198616915b82811015620002495788860151825594840194600190910190840162000228565b5085821015620002685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61143080620002886000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063715018a6116100a2578063b88d4fde11610071578063b88d4fde14610239578063c87b56dd1461024c578063cd279c7c1461025f578063e985e9c514610272578063f2fde38b1461028557600080fd5b8063715018a6146102055780638da5cb5b1461020d57806395d89b411461021e578063a22cb4651461022657600080fd5b806323b872dd116100e957806323b872dd1461019857806342842e0e146101ab57806342966c68146101be5780636352211e146101d157806370a08231146101e457600080fd5b806301ffc9a71461011b57806306fdde0314610143578063081812fc14610158578063095ea7b314610183575b600080fd5b61012e610129366004610f0f565b610298565b60405190151581526020015b60405180910390f35b61014b6102a9565b60405161013a9190610f7c565b61016b610166366004610f8f565b61033b565b6040516001600160a01b03909116815260200161013a565b610196610191366004610fc4565b610364565b005b6101966101a6366004610fee565b610373565b6101966101b9366004610fee565b610403565b6101966101cc366004610f8f565b610423565b61016b6101df366004610f8f565b61042f565b6101f76101f236600461102a565b61043a565b60405190815260200161013a565b610196610482565b6007546001600160a01b031661016b565b61014b610496565b610196610234366004611045565b6104a5565b61019661024736600461110d565b6104b0565b61014b61025a366004610f8f565b6104c7565b61019661026d366004611189565b6104d2565b61012e6102803660046111f4565b6104ee565b61019661029336600461102a565b61051c565b60006102a38261055a565b92915050565b6060600080546102b890611227565b80601f01602080910402602001604051908101604052809291908181526020018280546102e490611227565b80156103315780601f1061030657610100808354040283529160200191610331565b820191906000526020600020905b81548152906001019060200180831161031457829003601f168201915b5050505050905090565b60006103468261057f565b506000828152600460205260409020546001600160a01b03166102a3565b61036f8282336105b8565b5050565b6001600160a01b0382166103a257604051633250574960e11b8152600060048201526024015b60405180910390fd5b60006103af8383336105c5565b9050836001600160a01b0316816001600160a01b0316146103fd576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610399565b50505050565b61041e838383604051806020016040528060008152506104b0565b505050565b61036f600082336105c5565b60006102a38261057f565b60006001600160a01b038216610466576040516322718ad960e21b815260006004820152602401610399565b506001600160a01b031660009081526003602052604090205490565b61048a6106be565b61049460006106eb565b565b6060600180546102b890611227565b61036f33838361073d565b6104bb848484610373565b6103fd848484846107dc565b60606102a382610905565b6104da6106be565b6104e48383610a16565b61041e8282610a30565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6105246106be565b6001600160a01b03811661054e57604051631e4fbdf760e01b815260006004820152602401610399565b610557816106eb565b50565b60006001600160e01b03198216632483248360e11b14806102a357506102a382610a80565b6000818152600260205260408120546001600160a01b0316806102a357604051637e27328960e01b815260048101849052602401610399565b61041e8383836001610ad0565b6000828152600260205260408120546001600160a01b03908116908316156105f2576105f2818486610bd6565b6001600160a01b038116156106305761060f600085600080610ad0565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561065f576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6007546001600160a01b031633146104945760405163118cdaa760e01b8152336004820152602401610399565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661076f57604051630b61174360e31b81526001600160a01b0383166004820152602401610399565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156103fd57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061081e903390889087908790600401611261565b6020604051808303816000875af1925050508015610859575060408051601f3d908101601f191682019092526108569181019061129e565b60015b6108c2573d808015610887576040519150601f19603f3d011682016040523d82523d6000602084013e61088c565b606091505b5080516000036108ba57604051633250574960e11b81526001600160a01b0385166004820152602401610399565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146108fe57604051633250574960e11b81526001600160a01b0385166004820152602401610399565b5050505050565b60606109108261057f565b506000828152600660205260408120805461092a90611227565b80601f016020809104026020016040519081016040528092919081815260200182805461095690611227565b80156109a35780601f10610978576101008083540402835291602001916109a3565b820191906000526020600020905b81548152906001019060200180831161098657829003601f168201915b5050505050905060006109c160408051602081019091526000815290565b905080516000036109d3575092915050565b815115610a055780826040516020016109ed9291906112bb565b60405160208183030381529060405292505050919050565b610a0e84610c3a565b949350505050565b61036f828260405180602001604052806000815250610caf565b6000828152600660205260409020610a48828261133a565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b60006001600160e01b031982166380ac58cd60e01b1480610ab157506001600160e01b03198216635b5e139f60e01b145b806102a357506301ffc9a760e01b6001600160e01b03198316146102a3565b8080610ae457506001600160a01b03821615155b15610ba6576000610af48461057f565b90506001600160a01b03831615801590610b205750826001600160a01b0316816001600160a01b031614155b8015610b335750610b3181846104ee565b155b15610b5c5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610399565b8115610ba45783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b610be1838383610cc6565b61041e576001600160a01b038316610c0f57604051637e27328960e01b815260048101829052602401610399565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610399565b6060610c458261057f565b506000610c5d60408051602081019091526000815290565b90506000815111610c7d5760405180602001604052806000815250610ca8565b80610c8784610d29565b604051602001610c989291906112bb565b6040516020818303038152906040525b9392505050565b610cb98383610dbc565b61041e60008484846107dc565b60006001600160a01b03831615801590610a0e5750826001600160a01b0316846001600160a01b03161480610d005750610d0084846104ee565b80610a0e5750506000908152600460205260409020546001600160a01b03908116911614919050565b60606000610d3683610e21565b600101905060008167ffffffffffffffff811115610d5657610d56611081565b6040519080825280601f01601f191660200182016040528015610d80576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610d8a57509392505050565b6001600160a01b038216610de657604051633250574960e11b815260006004820152602401610399565b6000610df4838360006105c5565b90506001600160a01b0381161561041e576040516339e3563760e11b815260006004820152602401610399565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610e605772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610e8c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610eaa57662386f26fc10000830492506010015b6305f5e1008310610ec2576305f5e100830492506008015b6127108310610ed657612710830492506004015b60648310610ee8576064830492506002015b600a83106102a35760010192915050565b6001600160e01b03198116811461055757600080fd5b600060208284031215610f2157600080fd5b8135610ca881610ef9565b60005b83811015610f47578181015183820152602001610f2f565b50506000910152565b60008151808452610f68816020860160208601610f2c565b601f01601f19169290920160200192915050565b602081526000610ca86020830184610f50565b600060208284031215610fa157600080fd5b5035919050565b80356001600160a01b0381168114610fbf57600080fd5b919050565b60008060408385031215610fd757600080fd5b610fe083610fa8565b946020939093013593505050565b60008060006060848603121561100357600080fd5b61100c84610fa8565b925061101a60208501610fa8565b9150604084013590509250925092565b60006020828403121561103c57600080fd5b610ca882610fa8565b6000806040838503121561105857600080fd5b61106183610fa8565b91506020830135801515811461107657600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156110b2576110b2611081565b604051601f8501601f19908116603f011681019082821181831017156110da576110da611081565b816040528093508581528686860111156110f357600080fd5b858560208301376000602087830101525050509392505050565b6000806000806080858703121561112357600080fd5b61112c85610fa8565b935061113a60208601610fa8565b925060408501359150606085013567ffffffffffffffff81111561115d57600080fd5b8501601f8101871361116e57600080fd5b61117d87823560208401611097565b91505092959194509250565b60008060006060848603121561119e57600080fd5b6111a784610fa8565b925060208401359150604084013567ffffffffffffffff8111156111ca57600080fd5b8401601f810186136111db57600080fd5b6111ea86823560208401611097565b9150509250925092565b6000806040838503121561120757600080fd5b61121083610fa8565b915061121e60208401610fa8565b90509250929050565b600181811c9082168061123b57607f821691505b60208210810361125b57634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061129490830184610f50565b9695505050505050565b6000602082840312156112b057600080fd5b8151610ca881610ef9565b600083516112cd818460208801610f2c565b8351908301906112e1818360208801610f2c565b01949350505050565b601f82111561041e576000816000526020600020601f850160051c810160208610156113135750805b601f850160051c820191505b818110156113325782815560010161131f565b505050505050565b815167ffffffffffffffff81111561135457611354611081565b611368816113628454611227565b846112ea565b602080601f83116001811461139d57600084156113855750858301515b600019600386901b1c1916600185901b178555611332565b600085815260208120601f198616915b828110156113cc578886015182559484019460019091019084016113ad565b50858210156113ea5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea264697066735822122046da1d9cfc7c225e4655204f464e2ecbb316a6284c51c9c338433a1abb5919f864736f6c63430008170033" + access(all) let bridgedNFTCodeChunks = [ "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f7274204d6574616461746156696577732066726f6d203078303030303030303030303030303030310a696d706f727420566965775265736f6c7665722066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a696d706f72742045564d2066726f6d203078303030303030303030303030303030310a0a696d706f7274204943726f7373564d2066726f6d203078303030303030303030303030303030370a696d706f7274204945564d4272696467654e46544d696e7465722066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467654e4654457363726f772066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d427269646765436f6e6669672066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467655574696c732066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467652066726f6d203078303030303030303030303030303030370a696d706f72742043726f7373564d4e46542066726f6d203078303030303030303030303030303030370a0a2f2f2f205468697320636f6e747261637420697320612074656d706c617465207573656420627920466c6f7745564d42726964676520746f20646566696e652045564d2d6e6174697665204e46547320627269646765642066726f6d20466c6f772045564d20746f20466c6f772e0a2f2f2f2055706f6e206465706c6f796d656e74206f66207468697320636f6e74726163742c2074686520636f6e7472616374206e616d65206973206465726976656420617320612066756e6374696f6e206f6620746865206173736574207479706520286865726520616e2045524337323120616b610a2f2f2f20616e204e46542920616e642074686520636f6e747261637427732045564d20616464726573732e20546865206465726976656420636f6e7472616374206e616d65206973207468656e206a6f696e65642077697468207468697320636f6e7472616374277320636f64652c0a2f2f2f207072657061726564206173206368756e6b7320696e20466c6f7745564d42726964676554656d706c61746573206265666f7265206265696e67206465706c6f79656420746f2074686520466c6f772045564d20427269646765206163636f756e742e0a2f2f2f0a2f2f2f204f6e206272696467696e672c2074686520455243373231206973207472616e7366657272656420746f2074686520627269646765277320436164656e63654f776e65644163636f756e742045564d206164647265737320616e642061206e6577204e4654206973206d696e7465642066726f6d0a2f2f2f207468697320636f6e747261637420746f20746865206272696467696e672063616c6c65722e204f6e2072657475726e20746f20466c6f772045564d2c2074686520726576657273652070726f6365737320697320666f6c6c6f776564202d2074686520746f6b656e206973206275726e65640a2f2f2f20696e207468697320636f6e747261637420616e642074686520455243373231206973207472616e7366657272656420746f2074686520646566696e656420726563697069656e742e20496e2074686973207761792c2074686520436164656e636520746f6b656e206163747320617320610a2f2f2f20726570726573656e746174696f6e206f6620626f7468207468652045564d204e465420616e642074687573206f776e6572736869702072696768747320746f2069742075706f6e206272696467696e67206261636b20746f20466c6f772045564d2e0a2f2f2f0a2f2f2f20546f20627269646765206265747765656e20564d732c20612063616c6c65722063616e20656974686572207573652074686520636f6e7472616374206d6574686f647320646566696e65642062656c6f772c206f72207573652074686520466c6f7745564d42726964676527730a2f2f2f206272696467696e67206d6574686f64732077686963682077696c6c2070726f6772616d61746963616c6c7920726f757465206272696467696e672063616c6c7320746f207468697320636f6e74726163742e0a2f2f2f0a2f2f20544f444f3a20496d706c656d656e74204e465420636f6e747261637420696e74657266616365206f6e636520763220617661696c61626c65206c6f63616c6c790a61636365737328616c6c2920636f6e747261637420", "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20", @@ -39,6 +41,11 @@ fun getCompiledFactoryBytecode(): String { return compiledFactoryBytecode } +access(all) +fun getCompiledERC721Bytecode(): String { + return compiledERC721Bytecode +} + access(all) fun getBridgedNFTCodeChunks(): [String] { return bridgedNFTCodeChunks diff --git a/cadence/transactions/example-assets/safe_mint_erc721.cdc b/cadence/transactions/example-assets/safe_mint_erc721.cdc index 10e65f94..bf7b1955 100644 --- a/cadence/transactions/example-assets/safe_mint_erc721.cdc +++ b/cadence/transactions/example-assets/safe_mint_erc721.cdc @@ -4,7 +4,7 @@ import "FlowEVMBridgeUtils" transaction( recipientHexAddress: String, - tokenId: UInt64, + tokenId: UInt256, uri: String, erc721HexAddress: String, gasLimit: UInt64 @@ -32,6 +32,6 @@ transaction( gasLimit: gasLimit, value: EVM.Balance(attoflow: 0) ) - assert(callResult.status == EVM.Status.successful, message: "ERC721 mint failed") + assert(callResult.status == EVM.Status.successful, message: "ERC721 mint failed with code: ".concat(callResult.errorCode.toString())) } -} \ No newline at end of file +} diff --git a/flow.json b/flow.json index a2ec42d7..5c80d499 100644 --- a/flow.json +++ b/flow.json @@ -42,6 +42,13 @@ "testing": "0000000000000007" } }, + "EVMDeployer": { + "source": "./cadence/contracts/test/EVMDeployer.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000009" + } + }, "ExampleNFT": { "source": "./cadence/contracts/example-assets/ExampleNFT.cdc", "aliases": { From 955a92316dd877239491e0093f2194d2ad500421 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:50:23 -0500 Subject: [PATCH 35/39] add onboarding test coverage --- cadence/tests/flow_evm_bridge_tests.cdc | 119 +++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index 387587cd..6932e3e8 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -8,8 +8,18 @@ access(all) let bridgeAccount = Test.getAccount(0x0000000000000007) access(all) let exampleNFTAccount = Test.getAccount(0x0000000000000008) access(all) let exampleERC721Account = Test.getAccount(0x0000000000000009) access(all) let alice = Test.createAccount() + +// ExampleNFT values +access(all) let exampleNFTIdentifier = "A.0000000000000008.ExampleNFT.NFT" +access(all) let exampleNFTTokenName = "Example NFT" +access(all) let exampleNFTTokenDescription = "Example NFT token description" +access(all) let exampleNFTTokenThumbnail = "https://examplenft.com/thumbnail.png" + +// ERC721 values +access(all) let erc721Name = "NAME" +access(all) let erc721Symbol = "SYMBOL" access(all) let erc721ID: UInt256 = 42 -access(all) let erc721URI = "ipfs://QmXf1Z6z5Y" +access(all) let erc721URI = "URI" access(all) fun setup() { @@ -165,6 +175,12 @@ fun setup() { arguments: [getCompiledERC721Bytecode(), UInt(0)] ) Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "ExampleNFT", + path: "../contracts/example-assets/ExampleNFT.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) } access(all) @@ -192,6 +208,31 @@ fun testCreateCOASucceeds() { Test.assertEqual(40, stringAddress!.length) } +access(all) +fun testMintExampleNFTSucceeds() { + let setupCollectionResult = executeTransaction( + "../transactions/example-assets/setup_collection.cdc", + [], + alice + ) + Test.expect(setupCollectionResult, Test.beSucceeded()) + + let mintExampleNFTResult = executeTransaction( + "../transactions/example-assets/mint_nft.cdc", + [alice.address, exampleNFTTokenName, exampleNFTTokenDescription, exampleNFTTokenThumbnail, [], [], []], + exampleNFTAccount + ) + Test.expect(mintExampleNFTResult, Test.beSucceeded()) + + let aliceIDResult = executeScript( + "../scripts/nft/get_ids.cdc", + [alice.address, "cadenceExampleNFTCollection"] + ) + Test.expect(aliceIDResult, Test.beSucceeded()) + let aliceOwnedIDs = aliceIDResult.returnValue as! [UInt64]? ?? panic("Problem getting ExampleNFT IDs") + Test.assertEqual(1, aliceOwnedIDs.length) +} + access(all) fun testMintERC721Succeeds() { let aliceCOAAddressResult = executeScript( @@ -211,8 +252,82 @@ fun testMintERC721Succeeds() { let mintERC721Result = executeTransaction( "../transactions/example-assets/safe_mint_erc721.cdc", - [aliceCOAAddressString, erc721ID, erc721URI, erc721AddressString, UInt64(150_000)], + [aliceCOAAddressString, erc721ID, erc721URI, erc721AddressString, UInt64(200_000)], exampleERC721Account ) Test.expect(mintERC721Result, Test.beSucceeded()) } + +access(all) +fun testOnboardByTypeSucceeds() { + var onboaringRequiredResult = executeScript( + "../scripts/bridge/type_requires_onboarding.cdc", + [exampleNFTIdentifier] + ) + Test.expect(onboaringRequiredResult, Test.beSucceeded()) + var requiresOnboarding = onboaringRequiredResult.returnValue as! Bool? ?? panic("Problem getting onboarding requirement") + Test.assertEqual(true, requiresOnboarding) + + var onboardingResult = executeTransaction( + "../transactions/bridge/onboard_by_type.cdc", + [exampleNFTIdentifier], + alice + ) + Test.expect(onboardingResult, Test.beSucceeded()) + + onboaringRequiredResult = executeScript( + "../scripts/bridge/type_requires_onboarding.cdc", + [exampleNFTIdentifier] + ) + Test.expect(onboaringRequiredResult, Test.beSucceeded()) + requiresOnboarding = onboaringRequiredResult.returnValue as! Bool? ?? panic("Problem getting onboarding requirement") + Test.assertEqual(false, requiresOnboarding) + + onboardingResult = executeTransaction( + "../transactions/bridge/onboard_by_type.cdc", + [exampleNFTIdentifier], + alice + ) + Test.expect(onboardingResult, Test.beFailed()) +} + +access(all) +fun testOnboardByEVMAddressSucceeds() { + let erc721AddressResult = executeScript( + "../scripts/test/get_deployed_erc721_address_string.cdc", + [] + ) + Test.expect(erc721AddressResult, Test.beSucceeded()) + let erc721AddressString = erc721AddressResult.returnValue as! String? ?? panic("Problem getting COA address as String") + Test.assertEqual(40, erc721AddressString.length) + + var onboaringRequiredResult = executeScript( + "../scripts/bridge/evm_address_requires_onboarding.cdc", + [erc721AddressString] + ) + Test.expect(onboaringRequiredResult, Test.beSucceeded()) + var requiresOnboarding = onboaringRequiredResult.returnValue as! Bool? ?? panic("Problem getting onboarding requirement") + Test.assertEqual(true, requiresOnboarding) + + var onboardingResult = executeTransaction( + "../transactions/bridge/onboard_by_evm_address.cdc", + [erc721AddressString], + alice + ) + Test.expect(onboardingResult, Test.beSucceeded()) + + onboaringRequiredResult = executeScript( + "../scripts/bridge/evm_address_requires_onboarding.cdc", + [erc721AddressString] + ) + Test.expect(onboaringRequiredResult, Test.beSucceeded()) + requiresOnboarding = onboaringRequiredResult.returnValue as! Bool? ?? panic("Problem getting onboarding requirement") + Test.assertEqual(false, requiresOnboarding) + + onboardingResult = executeTransaction( + "../transactions/bridge/onboard_by_evm_address.cdc", + [erc721AddressString], + alice + ) + Test.expect(onboardingResult, Test.beFailed()) +} \ No newline at end of file From ee2cc6ef8d2c351c98d0bc9837ca843ecf507524 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:30:24 -0500 Subject: [PATCH 36/39] add test coverage - found issue with test setup --- cadence/scripts/utils/is_owner.cdc | 22 +++++++ cadence/tests/flow_evm_bridge_tests.cdc | 73 +++++++++++++++++++--- cadence/tests/test_helpers.cdc | 13 +++- cadence/transactions/test/add_contract.cdc | 5 ++ flow.json | 2 +- 5 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 cadence/scripts/utils/is_owner.cdc create mode 100644 cadence/transactions/test/add_contract.cdc diff --git a/cadence/scripts/utils/is_owner.cdc b/cadence/scripts/utils/is_owner.cdc new file mode 100644 index 00000000..4906ce6b --- /dev/null +++ b/cadence/scripts/utils/is_owner.cdc @@ -0,0 +1,22 @@ +import "EVM" + +import "FlowEVMBridgeUtils" + +/// Returns whether the given owner (hex-encoded EVM address - minus 0x prefix) is the owner of the given ERC721 NFT +/// defined at the hex-encoded EVM contract address +/// +/// @param ofNFT: The ERC721 ID of the NFT +/// @param owner: The hex-encoded EVM address of the owner without the 0x prefix +/// @param evmContractAddress: The hex-encoded EVM contract address of the ERC721 contract without the 0x prefix +/// +/// @return Whether the given owner is the owner of the given ERC721 NFT. Reverts on call failure. +/// +access(all) fun main(ofNFT: UInt256, owner: String, evmContractAddress: String): Bool { + return FlowEVMBridgeUtils.isOwner( + ofNFT: ofNFT, + owner: FlowEVMBridgeUtils.getEVMAddressFromHexString(address: owner) + ?? panic("Invalid owner address"), + evmContractAddress: FlowEVMBridgeUtils.getEVMAddressFromHexString(address: evmContractAddress) + ?? panic("Invalid EVM contract address") + ) +} diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index 6932e3e8..e2571875 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -54,7 +54,7 @@ fun setup() { arguments: [] ) Test.expect(err, Test.beNil()) - + // Update EVM contract with proposed bridge-supporting COA integration let updateResult = executeTransaction( "../transactions/test/update_contract.cdc", @@ -145,12 +145,15 @@ fun setup() { arguments: [] ) Test.expect(err, Test.beNil()) - err = Test.deployContract( - name: "EVMBridgeRouter", - path: "../contracts/bridge/EVMBridgeRouter.cdc", - arguments: [serviceAccount.address, "FlowEVMBridge"] + + // Deploy EVMBridgeRouter manually to service account for COA -> bridge integration + let deployResult = executeTransaction( + "../transactions/test/add_contract.cdc", + ["EVMBridgeRouter", getEVMBridgeRouterCode(), bridgeAccount.address, "FlowEVMBridge"], + serviceAccount ) - Test.expect(err, Test.beNil()) + Test.expect(updateResult, Test.beSucceeded()) + Test.assertEqual(true, getAccount(serviceAccount.address).contracts.names.contains("EVMBridgeRouter")) // Transfer ERC721 deployer some $FLOW let fundERC721AccountResult = executeTransaction( @@ -183,6 +186,18 @@ fun setup() { Test.expect(err, Test.beNil()) } +// TODO: Figure out how to test EVMBridgeRouter given it needs to be deployed to the service account +// and we can't seem to alter service account storage from the test suite +access(all) +fun testIsBridgeRouterConfiguredSucceeds() { + let isConfiguredResult = executeScript( + "../scripts/test/is_bridge_router_configured.cdc", + [] + ) + Test.expect(isConfiguredResult, Test.beSucceeded()) + Test.assertEqual(true, isConfiguredResult.returnValue as! Bool? ?? panic("Problem getting Router")) +} + access(all) fun testCreateCOASucceeds() { let transferFlowResult = executeTransaction( @@ -274,7 +289,7 @@ fun testOnboardByTypeSucceeds() { alice ) Test.expect(onboardingResult, Test.beSucceeded()) - + onboaringRequiredResult = executeScript( "../scripts/bridge/type_requires_onboarding.cdc", [exampleNFTIdentifier] @@ -315,7 +330,7 @@ fun testOnboardByEVMAddressSucceeds() { alice ) Test.expect(onboardingResult, Test.beSucceeded()) - + onboaringRequiredResult = executeScript( "../scripts/bridge/evm_address_requires_onboarding.cdc", [erc721AddressString] @@ -330,4 +345,46 @@ fun testOnboardByEVMAddressSucceeds() { alice ) Test.expect(onboardingResult, Test.beFailed()) +} + +access(all) +fun testBridgeCadenceNativeNFTToEVMSucceeds() { + let aliceIDResult = executeScript( + "../scripts/nft/get_ids.cdc", + [alice.address, "cadenceExampleNFTCollection"] + ) + Test.expect(aliceIDResult, Test.beSucceeded()) + let aliceOwnedIDs = aliceIDResult.returnValue as! [UInt64]? ?? panic("Problem getting ExampleNFT IDs") + Test.assertEqual(1, aliceOwnedIDs.length) + + let aliceCOAAddressResult = executeScript( + "../scripts/evm/get_evm_address_string.cdc", + [alice.address] + ) + Test.expect(aliceCOAAddressResult, Test.beSucceeded()) + let aliceCOAAddressString = aliceCOAAddressResult.returnValue as! String? ?? panic("Problem getting COA address as String") + Test.assertEqual(40, aliceCOAAddressString.length) + + // TODO: This fails because EVMBridgeRouter.Router does not configure a resource in the service account + let bridgeToEVMResult = executeTransaction( + "../transactions/bridge/bridge_nft_to_evm.cdc", + [exampleNFTAccount.address, "ExampleNFT", aliceOwnedIDs[0]], + alice + ) + Test.expect(bridgeToEVMResult, Test.beSucceeded()) + + var associatedEVMAddressResult = executeScript( + "../scripts/bridge/get_associated_evm_address.cdc", + [exampleNFTIdentifier] + ) + Test.expect(associatedEVMAddressResult, Test.beSucceeded()) + let associatedEVMAddressString = associatedEVMAddressResult.returnValue as! String? ?? panic("Problem getting EVM Address as String") + Test.assertEqual(40, associatedEVMAddressString.length) + + var isOwnerResult = executeScript( + "../scripts/utils/is_owner.cdc", + [UInt256(aliceOwnedIDs[0]), aliceCOAAddressString, associatedEVMAddressString] + ) + Test.expect(isOwnerResult, Test.beSucceeded()) + Test.assertEqual(true, isOwnerResult.returnValue as! Bool? ?? panic("Problem getting owner status")) } \ No newline at end of file diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index e54bb5fd..5c5b5394 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -1,9 +1,15 @@ +/// This file contains constants for contract code which is used for bridge suite configuration. +/// See the python util `get_code_hex.py` to retrieve the hex-encoded Cadence either with or +/// without a separator (`{{CONTRACT_NAME}}` used in templates to "chunk" template code). + access(all) let evmUpdateCode = "696d706f72742043727970746f0a0a696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a61636365737328616c6c290a636f6e74726163742045564d207b0a0a202020202f2f20456e7469746c656d656e747320656e61626c696e672066696e65722d6772616e65642061636365737320636f6e74726f6c206f6e206120436164656e63654f776e65644163636f756e740a2020202061636365737328616c6c2920656e7469746c656d656e742056616c69646174650a2020202061636365737328616c6c2920656e7469746c656d656e742057697468647261770a2020202061636365737328616c6c2920656e7469746c656d656e742043616c6c0a2020202061636365737328616c6c2920656e7469746c656d656e74204465706c6f790a2020202061636365737328616c6c2920656e7469746c656d656e74204f776e65720a2020202061636365737328616c6c2920656e7469746c656d656e74204272696467650a0a2020202061636365737328616c6c290a202020206576656e7420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a205b55496e74383b2032305d290a0a202020202f2f2f2045564d4164647265737320697320616e2045564d2d636f6d70617469626c6520616464726573730a2020202061636365737328616c6c290a202020207374727563742045564d41646472657373207b0a0a20202020202020202f2f2f204279746573206f662074686520616464726573730a202020202020202061636365737328616c6c290a20202020202020206c65742062797465733a205b55496e74383b2032305d0a0a20202020202020202f2f2f20436f6e737472756374732061206e65772045564d20616464726573732066726f6d2074686520676976656e206279746520726570726573656e746174696f6e0a20202020202020207669657720696e69742862797465733a205b55496e74383b2032305d29207b0a20202020202020202020202073656c662e6279746573203d2062797465730a20202020202020207d0a0a20202020202020202f2f2f2042616c616e6365206f662074686520616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a2020202020202020202020206c65742062616c616e6365203d20496e7465726e616c45564d2e62616c616e6365280a20202020202020202020202020202020616464726573733a2073656c662e62797465730a202020202020202020202020290a20202020202020202020202072657475726e2042616c616e6365286174746f666c6f773a2062616c616e6365290a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207374727563742042616c616e6365207b0a0a20202020202020202f2f2f205468652062616c616e636520696e206174746f2d464c4f570a20202020202020202f2f2f204174746f2d464c4f572069732074686520736d616c6c6573742064656e6f6d696e6174696f6e206f6620464c4f5720283165313820464c4f57290a20202020202020202f2f2f2074686174206973207573656420746f2073746f7265206163636f756e742062616c616e63657320696e736964652045564d0a20202020202020202f2f2f2073696d696c617220746f207468652077617920574549206973207573656420746f2073746f72652045544820646976697369626c6520746f20313820646563696d616c20706c616365732e0a202020202020202061636365737328616c6c290a2020202020202020766172206174746f666c6f773a2055496e740a0a20202020202020202f2f2f20436f6e737472756374732061206e65772062616c616e63650a202020202020202061636365737328616c6c290a20202020202020207669657720696e6974286174746f666c6f773a2055496e7429207b0a20202020202020202020202073656c662e6174746f666c6f77203d206174746f666c6f770a20202020202020207d0a0a20202020202020202f2f2f2053657473207468652062616c616e636520627920612055466978363420283820646563696d616c20706f696e7473292c2074686520666f726d61740a20202020202020202f2f2f2074686174206973207573656420696e20436164656e636520746f2073746f726520464c4f5720746f6b656e732e0a202020202020202061636365737328616c6c290a202020202020202066756e20736574464c4f5728666c6f773a20554669783634297b0a20202020202020202020202073656c662e6174746f666c6f77203d20496e7465726e616c45564d2e63617374546f4174746f464c4f572862616c616e63653a20666c6f77290a20202020202020207d0a0a20202020202020202f2f2f204361737473207468652062616c616e636520746f2061205546697836342028726f756e64696e6720646f776e290a20202020202020202f2f2f205761726e696e67212063617374696e6720612062616c616e636520746f20612055466978363420776869636820737570706f7274732061206c6f776572206c6576656c206f6620707265636973696f6e0a20202020202020202f2f2f20283820646563696d616c20706f696e747320696e20636f6d7061726520746f20313829206d6967687420726573756c7420696e20726f756e64696e6720646f776e206572726f722e0a20202020202020202f2f2f205573652074686520746f4174746f466c6f772066756e6374696f6e20696620796f752063617265206e656564206d6f72652061636375726163792e0a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e464c4f5728293a20554669783634207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63617374546f464c4f572862616c616e63653a2073656c662e6174746f666c6f77290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e73207468652062616c616e636520696e204174746f2d464c4f570a202020202020202061636365737328616c6c290a2020202020202020766965772066756e20696e4174746f464c4f5728293a2055496e74207b0a20202020202020202020202072657475726e2073656c662e6174746f666c6f770a20202020202020207d0a202020207d0a0a202020202f2f2f207265706f7274732074686520737461747573206f662065766d20657865637574696f6e2e0a2020202061636365737328616c6c2920656e756d205374617475733a2055496e7438207b0a20202020202020202f2f2f2069732028726172656c79292072657475726e6564207768656e2073746174757320697320756e6b6e6f776e0a20202020202020202f2f2f20616e6420736f6d657468696e672068617320676f6e6520766572792077726f6e672e0a202020202020202061636365737328616c6c29206361736520756e6b6e6f776e0a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206661696c6564206174207468652076616c69646174696f6e20737465702028652e672e206e6f6e6365206d69736d61746368292e0a20202020202020202f2f2f20416e20696e76616c6964207472616e73616374696f6e2f63616c6c2069732072656a656374656420746f2062652065786563757465640a20202020202020202f2f2f206f7220626520696e636c7564656420696e206120626c6f636b2e0a202020202020202061636365737328616c6c29206361736520696e76616c69640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c206275742074686520766d20686173207265706f7274656420616e206572726f722061730a20202020202020202f2f2f20746865206f7574636f6d65206f6620657865637574696f6e2028652e672e2072756e6e696e67206f7574206f6620676173292e0a20202020202020202f2f2f2041206661696c65642074782f63616c6c20697320696e636c7564656420696e206120626c6f636b2e0a20202020202020202f2f2f204e6f746520746861742072657375626d697373696f6e206f662061206661696c6564207472616e73616374696f6e20776f756c640a20202020202020202f2f2f20726573756c7420696e20696e76616c69642073746174757320696e20746865207365636f6e6420617474656d70742c20676976656e0a20202020202020202f2f2f20746865206e6f6e636520776f756c6420626520636f6d6520696e76616c69642e0a202020202020202061636365737328616c6c292063617365206661696c65640a0a20202020202020202f2f2f2069732072657475726e6564207768656e20657865637574696f6e206f6620616e2065766d207472616e73616374696f6e2f63616c6c0a20202020202020202f2f2f20686173206265656e207375636365737366756c20616e64206e6f206572726f72206973207265706f727465642062792074686520766d2e0a202020202020202061636365737328616c6c292063617365207375636365737366756c0a202020207d0a0a202020202f2f2f207265706f72747320746865206f7574636f6d65206f662065766d207472616e73616374696f6e2f63616c6c20657865637574696f6e20617474656d70740a2020202061636365737328616c6c292073747275637420526573756c74207b0a20202020202020202f2f2f20737461747573206f662074686520657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c6574207374617475733a205374617475730a0a20202020202020202f2f2f206572726f7220636f646520286572726f7220636f6465207a65726f206d65616e73206e6f206572726f72290a202020202020202061636365737328616c6c290a20202020202020206c6574206572726f72436f64653a2055496e7436340a0a20202020202020202f2f2f2072657475726e732074686520616d6f756e74206f6620676173206d65746572656420647572696e670a20202020202020202f2f2f2065766d20657865637574696f6e0a202020202020202061636365737328616c6c290a20202020202020206c657420676173557365643a2055496e7436340a0a20202020202020202f2f2f2072657475726e7320746865206461746120746861742069732072657475726e65642066726f6d0a20202020202020202f2f2f207468652065766d20666f72207468652063616c6c2e20466f7220636f612e6465706c6f790a20202020202020202f2f2f2063616c6c732069742072657475726e73207468652061646472657373206279746573206f66207468650a20202020202020202f2f2f206e65776c79206465706c6f79656420636f6e74726163742e0a202020202020202061636365737328616c6c290a20202020202020206c657420646174613a205b55496e74385d0a0a2020202020202020696e6974280a2020202020202020202020207374617475733a205374617475732c0a2020202020202020202020206572726f72436f64653a2055496e7436342c0a202020202020202020202020676173557365643a2055496e7436342c0a202020202020202020202020646174613a205b55496e74385d0a202020202020202029207b0a20202020202020202020202073656c662e737461747573203d207374617475730a20202020202020202020202073656c662e6572726f72436f6465203d206572726f72436f64650a20202020202020202020202073656c662e67617355736564203d20676173557365640a20202020202020202020202073656c662e64617461203d20646174610a20202020202020207d0a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204164647265737361626c65207b0a20202020202020202f2f2f205468652045564d20616464726573730a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d416464726573730a202020207d0a0a2020202061636365737328616c6c290a202020207265736f7572636520436164656e63654f776e65644163636f756e743a204164647265737361626c65207b0a0a20202020202020206163636573732873656c66290a2020202020202020766172206164647265737342797465733a205b55496e74383b2032305d0a0a2020202020202020696e69742829207b0a2020202020202020202020202f2f206164647265737320697320696e697469616c6c792073657420746f207a65726f0a2020202020202020202020202f2f206275742075706461746564207468726f75676820696e697441646472657373206c617465720a2020202020202020202020202f2f207765206861766520746f20646f20746869732073696e6365207765206e656564207265736f75726365206964202875756964290a2020202020202020202020202f2f20746f2063616c63756c617465207468652045564d206164647265737320666f72207468697320636164656e6365206f776e6564206163636f756e740a20202020202020202020202073656c662e616464726573734279746573203d205b302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20302c20305d0a20202020202020207d0a0a202020202020202061636365737328636f6e7472616374290a202020202020202066756e20696e697441646472657373286164647265737342797465733a205b55496e74383b2032305d29207b0a20202020202020202020202f2f206f6e6c7920616c6c6f7720736574206164647265737320666f72207468652066697273742074696d650a20202020202020202020202f2f20636865636b206164647265737320697320656d7074790a202020202020202020202020666f72206974656d20696e2073656c662e616464726573734279746573207b0a20202020202020202020202020202020617373657274286974656d203d3d20302c206d6573736167653a2022616464726573732062797465206973206e6f7420656d70747922290a2020202020202020202020207d0a202020202020202020202073656c662e616464726573734279746573203d206164647265737342797465730a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e206164647265737328293a2045564d41646472657373207b0a2020202020202020202020202f2f20416c77617973206372656174652061206e65772045564d4164647265737320696e7374616e63650a20202020202020202020202072657475726e2045564d416464726573732862797465733a2073656c662e616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f204765742062616c616e6365206f662074686520636164656e6365206f776e6564206163636f756e740a202020202020202061636365737328616c6c290a2020202020202020766965772066756e2062616c616e636528293a2042616c616e6365207b0a20202020202020202020202072657475726e2073656c662e6164647265737328292e62616c616e636528290a20202020202020207d0a0a20202020202020202f2f2f204465706f736974732074686520676976656e207661756c7420696e746f2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369742866726f6d3a2040466c6f77546f6b656e2e5661756c7429207b0a202020202020202020202020496e7465726e616c45564d2e6465706f736974280a2020202020202020202020202020202066726f6d3a203c2d66726f6d2c0a20202020202020202020202020202020746f3a2073656c662e6164647265737342797465730a202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f2f205468652045564d2061646472657373206f662074686520636164656e6365206f776e6564206163636f756e7420626568696e6420616e20656e7469746c656d656e742c20616374696e672061732070726f6f66206f66206163636573730a2020202020202020616363657373284f776e6572207c2056616c6964617465290a2020202020202020766965772066756e2070726f7465637465644164647265737328293a2045564d41646472657373207b0a20202020202020202020202072657475726e2073656c662e6164647265737328290a20202020202020207d0a0a20202020202020202f2f2f20576974686472617773207468652062616c616e63652066726f6d2074686520636164656e6365206f776e6564206163636f756e7427732062616c616e63650a20202020202020202f2f2f204e6f7465207468617420616d6f756e747320736d616c6c6572207468616e2031306e4620283130652d38292063616e27742062652077697468647261776e0a20202020202020202f2f2f20676976656e207468617420466c6f7720546f6b656e205661756c747320757365205546697836347320746f2073746f72652062616c616e6365732e0a20202020202020202f2f2f2049662074686520676976656e2062616c616e636520636f6e76657273696f6e20746f2055466978363420726573756c747320696e0a20202020202020202f2f2f20726f756e64696e67206572726f722c20746869732066756e6374696f6e20776f756c64206661696c2e0a2020202020202020616363657373284f776e6572207c205769746864726177290a202020202020202066756e2077697468647261772862616c616e63653a2042616c616e6365293a2040466c6f77546f6b656e2e5661756c74207b0a2020202020202020202020206c6574207661756c74203c2d20496e7465726e616c45564d2e7769746864726177280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020616d6f756e743a2062616c616e63652e6174746f666c6f770a20202020202020202020202029206173212040466c6f77546f6b656e2e5661756c740a20202020202020202020202072657475726e203c2d7661756c740a20202020202020207d0a0a20202020202020202f2f2f204465706c6f7973206120636f6e747261637420746f207468652045564d20656e7669726f6e6d656e742e0a20202020202020202f2f2f2052657475726e73207468652061646472657373206f6620746865206e65776c79206465706c6f79656420636f6e74726163740a2020202020202020616363657373284f776e6572207c204465706c6f79290a202020202020202066756e206465706c6f79280a202020202020202020202020636f64653a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a2045564d41646472657373207b0a2020202020202020202020206c657420616464726573734279746573203d20496e7465726e616c45564d2e6465706c6f79280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020636f64653a20636f64652c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020290a20202020202020202020202072657475726e2045564d416464726573732862797465733a20616464726573734279746573290a20202020202020207d0a0a20202020202020202f2f2f2043616c6c7320612066756e6374696f6e20776974682074686520676976656e20646174612e0a20202020202020202f2f2f2054686520657865637574696f6e206973206c696d697465642062792074686520676976656e20616d6f756e74206f66206761730a2020202020202020616363657373284f776e6572207c2043616c6c290a202020202020202066756e2063616c6c280a202020202020202020202020746f3a2045564d416464726573732c0a202020202020202020202020646174613a205b55496e74385d2c0a2020202020202020202020206761734c696d69743a2055496e7436342c0a20202020202020202020202076616c75653a2042616c616e63650a2020202020202020293a20526573756c74207b0a20202020202020202020202072657475726e20496e7465726e616c45564d2e63616c6c280a2020202020202020202020202020202066726f6d3a2073656c662e6164647265737342797465732c0a20202020202020202020202020202020746f3a20746f2e62797465732c0a20202020202020202020202020202020646174613a20646174612c0a202020202020202020202020202020206761734c696d69743a206761734c696d69742c0a2020202020202020202020202020202076616c75653a2076616c75652e6174746f666c6f770a202020202020202020202020292061732120526573756c740a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a202020202020202061636365737328616c6c290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a202020202020202029207b0a20202020202020202020202045564d2e626f72726f774272696467654163636573736f7228292e6465706f7369744e4654286e66743a203c2d6e66742c20746f3a2073656c662e6164647265737328292c2066656550726f76696465723a2066656550726f7669646572290a20202020202020207d0a0a20202020202020202f2f2f20427269646765732074686520676976656e204e465420746f207468652045564d20656e7669726f6e6d656e742c20726571756972696e6720612050726f76696465722066726f6d20776869636820746f20776974686472617720612066656520746f2066756c66696c6c0a20202020202020202f2f2f207468652062726964676520726571756573740a2020202020202020616363657373284f776e6572207c20427269646765290a202020202020202066756e2077697468647261774e4654280a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a20202020202020202020202072657475726e203c2d2045564d2e626f72726f774272696467654163636573736f7228292e77697468647261774e4654280a2020202020202020202020202020202063616c6c65723a202673656c6620617320617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a20202020202020202020202020202020747970653a20747970652c0a2020202020202020202020202020202069643a2069642c0a2020202020202020202020202020202066656550726f76696465723a2066656550726f76696465720a202020202020202020202020290a20202020202020207d0a202020207d0a0a202020202f2f2f20437265617465732061206e657720636164656e6365206f776e6564206163636f756e740a2020202061636365737328616c6c290a2020202066756e20637265617465436164656e63654f776e65644163636f756e7428293a2040436164656e63654f776e65644163636f756e74207b0a20202020202020206c657420616363203c2d63726561746520436164656e63654f776e65644163636f756e7428290a20202020202020206c65742061646472203d20496e7465726e616c45564d2e637265617465436164656e63654f776e65644163636f756e7428757569643a206163632e75756964290a20202020202020206163632e696e697441646472657373286164647265737342797465733a2061646472290a2020202020202020656d697420436164656e63654f776e65644163636f756e7443726561746564286164647265737342797465733a2061646472290a202020202020202072657475726e203c2d6163630a202020207d0a0a202020202f2f2f2052756e7320616e206120524c502d656e636f6465642045564d207472616e73616374696f6e2c2064656475637473207468652067617320666565732c0a202020202f2f2f20616e64206465706f736974732074686520676173206665657320696e746f207468652070726f766964656420636f696e6261736520616464726573732e0a2020202061636365737328616c6c290a2020202066756e2072756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a202020202020202072657475726e20496e7465726e616c45564d2e72756e280a2020202020202020202020202020202074783a2074782c0a20202020202020202020202020202020636f696e626173653a20636f696e626173652e62797465730a2020202020202020292061732120526573756c740a202020207d0a0a202020202f2f2f206d75737452756e2072756e7320746865207472616e73616374696f6e207573696e672045564d2e72756e207965742069740a202020202f2f2f20726f6c6c6261636b2069662074686520747820657865637574696f6e2073746174757320697320756e6b6e6f776e206f7220696e76616c69642e0a202020202f2f2f204e6f746520746861742074686973206d6574686f6420646f6573206e6f7420726f6c6c6261636b206966207472616e73616374696f6e0a202020202f2f2f2069732065786563757465642062757420616e20766d206572726f72206973207265706f7274656420617320746865206f7574636f6d650a202020202f2f2f206f662074686520657865637574696f6e20287374617475733a206661696c6564292e0a2020202061636365737328616c6c290a2020202066756e206d75737452756e2874783a205b55496e74385d2c20636f696e626173653a2045564d41646472657373293a20526573756c74207b0a20202020202020206c65742072756e526573756c74203d2073656c662e72756e2874783a2074782c20636f696e626173653a20636f696e62617365290a2020202020202020617373657274280a20202020202020202020202072756e526573756c742e737461747573203d3d205374617475732e6661696c6564207c7c2072756e526573756c742e737461747573203d3d205374617475732e7375636365737366756c2c0a2020202020202020202020206d6573736167653a20227478206973206e6f742076616c696420666f7220657865637574696f6e220a2020202020202020290a202020202020202072657475726e2072756e526573756c740a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249285f2076616c7565733a205b416e795374727563745d293a205b55496e74385d207b0a202020202020202072657475726e20496e7465726e616c45564d2e656e636f64654142492876616c756573290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f64654142492874797065733a205b547970655d2c20646174613a205b55496e74385d293a205b416e795374727563745d207b0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e20656e636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a20202020202020205f2076616c7565733a205b416e795374727563745d0a20202020293a205b55496e74385d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a20202020202020206c657420617267756d656e7473203d20496e7465726e616c45564d2e656e636f64654142492876616c756573290a0a202020202020202072657475726e206d6574686f6449442e636f6e63617428617267756d656e7473290a202020207d0a0a2020202061636365737328616c6c290a2020202066756e206465636f6465414249576974685369676e6174757265280a20202020202020205f207369676e61747572653a20537472696e672c0a202020202020202074797065733a205b547970655d2c0a2020202020202020646174613a205b55496e74385d0a20202020293a205b416e795374727563745d207b0a20202020202020206c6574206d6574686f644944203d2048617368416c676f726974686d2e4b454343414b5f3235362e68617368280a2020202020202020202020207369676e61747572652e757466380a2020202020202020292e736c6963652866726f6d3a20302c207570546f3a2034290a0a2020202020202020666f72206279746520696e206d6574686f644944207b0a2020202020202020202020206966206279746520213d20646174612e72656d6f766546697273742829207b0a2020202020202020202020202020202070616e696328227369676e6174757265206d69736d6174636822290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e20496e7465726e616c45564d2e6465636f64654142492874797065733a2074797065732c20646174613a2064617461290a202020207d0a0a202020202f2f2f2056616c69646174696f6e526573756c742072657475726e732074686520726573756c74206f6620434f41206f776e6572736869702070726f6f662076616c69646174696f6e0a2020202061636365737328616c6c290a202020207374727563742056616c69646174696f6e526573756c74207b0a202020202020202061636365737328616c6c290a20202020202020206c657420697356616c69643a20426f6f6c0a0a202020202020202061636365737328616c6c290a20202020202020206c65742070726f626c656d3a20537472696e673f0a0a2020202020202020696e697428697356616c69643a20426f6f6c2c2070726f626c656d3a20537472696e673f29207b0a20202020202020202020202073656c662e697356616c6964203d20697356616c69640a20202020202020202020202073656c662e70726f626c656d203d2070726f626c656d0a20202020202020207d0a202020207d0a0a202020202f2f2f2076616c6964617465434f414f776e65727368697050726f6f662076616c696461746573206120434f41206f776e6572736869702070726f6f660a2020202061636365737328616c6c290a2020202066756e2076616c6964617465434f414f776e65727368697050726f6f66280a2020202020202020616464726573733a20416464726573732c0a2020202020202020706174683a205075626c6963506174682c0a20202020202020207369676e6564446174613a205b55496e74385d2c0a20202020202020206b6579496e64696365733a205b55496e7436345d2c0a20202020202020207369676e6174757265733a205b5b55496e74385d5d2c0a202020202020202065766d416464726573733a205b55496e74383b2032305d0a20202020293a2056616c69646174696f6e526573756c74207b0a0a20202020202020202f2f206d616b65207369676e6174757265207365742066697273740a20202020202020202f2f20636865636b206e756d626572206f66207369676e617475726573206d617463686573206e756d626572206f66206b657920696e64696365730a20202020202020206966206b6579496e64696365732e6c656e67746820213d207369676e6174757265732e6c656e677468207b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a20226b657920696e64696365732073697a6520646f65736e2774206d6174636820746865207369676e617475726573220a202020202020202020202020290a20202020202020207d0a0a2020202020202020766172207369676e61747572655365743a205b43727970746f2e4b65794c6973745369676e61747572655d203d205b5d0a2020202020202020666f72207369676e6174757265496e6465782c207369676e617475726520696e207369676e6174757265737b0a2020202020202020202020207369676e61747572655365742e617070656e642843727970746f2e4b65794c6973745369676e6174757265280a202020202020202020202020202020206b6579496e6465783a20496e74286b6579496e64696365735b7369676e6174757265496e6465785d292c0a202020202020202020202020202020207369676e61747572653a207369676e61747572650a20202020202020202020202029290a20202020202020207d0a0a20202020202020202f2f206665746368206163636f756e740a20202020202020206c657420616363203d206765744163636f756e742861646472657373290a0a20202020202020202f2f20636f6e737472756374696e67206b6579206c6973740a20202020202020206c6574206b65794c697374203d2043727970746f2e4b65794c69737428290a2020202020202020666f72207369676e617475726520696e207369676e6174757265536574207b0a2020202020202020202020206c6574206b6579203d206163632e6b6579732e676574286b6579496e6465783a207369676e61747572652e6b6579496e64657829210a20202020202020202020202061737365727428216b65792e69735265766f6b65642c206d6573736167653a20227265766f6b6564206b6579206973207573656422290a2020202020202020202020206b65794c6973742e616464280a20202020202020202020202020206b65792e7075626c69634b65792c0a202020202020202020202020202068617368416c676f726974686d3a206b65792e68617368416c676f726974686d2c0a20202020202020202020202020207765696768743a206b65792e7765696768742c0a2020202020202020202020290a20202020202020207d0a0a20202020202020206c657420697356616c6964203d206b65794c6973742e766572696679280a2020202020202020202020207369676e61747572655365743a207369676e61747572655365742c0a2020202020202020202020207369676e6564446174613a207369676e6564446174612c0a202020202020202020202020646f6d61696e53657061726174696f6e5461673a2022464c4f572d56302e302d75736572220a2020202020202020290a0a202020202020202069662021697356616c69647b0a20202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a20202020202020202020202020202020697356616c69643a2066616c73652c0a2020202020202020202020202020202070726f626c656d3a202274686520676976656e207369676e61747572657320617265206e6f742076616c6964206f722070726f7669646520656e6f75676820776569676874220a202020202020202020202020290a20202020202020207d0a0a20202020202020206c657420636f61526566203d206163632e6361706162696c69746965732e626f72726f773c2645564d2e436164656e63654f776e65644163636f756e743e2870617468290a0a2020202020202020696620636f61526566203d3d206e696c207b0a2020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202070726f626c656d3a2022636f756c64206e6f7420626f72726f7720627269646765206163636f756e742773207265736f75726365220a20202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f207665726966792065766d2061646472657373206d61746368696e670a20202020202020207661722061646472203d20636f61526566212e6164647265737328290a2020202020202020666f7220696e6465782c206974656d20696e20636f61526566212e6164647265737328292e6279746573207b0a2020202020202020202020206966206974656d20213d2065766d416464726573735b696e6465785d207b0a2020202020202020202020202020202072657475726e2056616c69646174696f6e526573756c74280a2020202020202020202020202020202020202020697356616c69643a2066616c73652c0a202020202020202020202020202020202020202070726f626c656d3a202265766d2061646472657373206d69736d61746368220a20202020202020202020202020202020290a2020202020202020202020207d0a20202020202020207d0a0a202020202020202072657475726e2056616c69646174696f6e526573756c74280a202020202020202020202020697356616c69643a20747275652c0a20202020202020202020202070726f626c656d3a206e696c0a2020202020202020290a202020207d0a0a202020202f2f2f2052657475726e732061207265666572656e636520746f20746865204272696467654163636573736f722064657369676e6174656420666f7220696e7465726e616c206272696467652072657175657374730a202020206163636573732873656c66290a20202020766965772066756e20626f72726f774272696467654163636573736f7228293a2061757468284272696467652920267b4272696467654163636573736f727d207b0a202020202020202072657475726e2073656c662e6163636f756e742e73746f726167652e626f72726f773c61757468284272696467652920267b4272696467654163636573736f727d3e2866726f6d3a202f73746f726167652f65766d427269646765526f75746572290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f77207265666572656e636520746f207468652045564d2062726964676522290a202020207d0a0a202020202f2f2f20496e7465726661636520666f722061207265736f75726365207768696368206163747320617320616e20656e747279706f696e7420746f2074686520564d206272696467650a2020202061636365737328616c6c290a202020207265736f7572636520696e74657266616365204272696467654163636573736f72207b0a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e465420746f2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a202020202020202020202020746f3a2045564d2e45564d416464726573732c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020290a0a20202020202020202f2f2f20456e64706f696e7420656e61626c696e67207468652062726964696e67206f6620616e204e46542066726f6d2045564d0a202020202020202061636365737328427269646765290a202020202020202066756e2077697468647261774e4654280a20202020202020202020202063616c6c65723a20617574682843616c6c292026436164656e63654f776e65644163636f756e742c0a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d0a202020207d0a7d0a" access(all) let compiledFactoryBytecode = "608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6129f4806100a56000396000f3fe60806040523480156200001157600080fd5b5060043610620000ab5760003560e01c80638da5cb5b116200006e5780638da5cb5b1462000155578063d56e0ccf1462000167578063daa09e54146200019e578063f2fde38b14620001b5578063f93241dd14620001cc57600080fd5b806304433bbc14620000b05780630a2c0ce914620000e4578063335f4c76146200010a57806361a169051462000132578063715018a61462000149575b600080fd5b620000c7620000c1366004620006ae565b620001e3565b6040516001600160a01b0390911681526020015b60405180910390f35b620000fb620000f5366004620006ef565b62000216565b604051620000db919062000775565b620001216200011b366004620006ef565b620002ca565b6040519015158152602001620000db565b620000c7620001433660046200078a565b620002f8565b62000153620003f9565b005b6000546001600160a01b0316620000c7565b620000c762000178366004620006ae565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b62000121620001af366004620006ef565b62000411565b62000153620001c6366004620006ef565b6200048c565b620000fb620001dd366004620006ef565b620004d4565b6000600182604051620001f791906200086c565b908152604051908190036020019020546001600160a01b031692915050565b6001600160a01b03811660009081526002602052604090208054606091906200023f906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200026d906200088a565b8015620002be5780601f106200029257610100808354040283529160200191620002be565b820191906000526020600020905b815481529060010190602001808311620002a057829003601f168201915b50505050509050919050565b6001600160a01b03811660009081526002602052604081208054620002ef906200088a565b15159392505050565b60006200030462000576565b600080546001600160a01b031687878787876040516200032490620005f5565b6200033596959493929190620008c6565b604051809103906000f08015801562000352573d6000803e3d6000fd5b509050806001856040516200036891906200086c565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152600290915220620003ad8582620009a4565b507fbebce54951ebf20c0dcd195a45bb2388d9ac8e38b5974e00bb63c5822dbe65f08188888888604051620003e795949392919062000a71565b60405180910390a19695505050505050565b6200040362000576565b6200040f6000620005a5565b565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526000906001600160a01b038316906301ffc9a790602401602060405180830381865afa15801562000460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000486919062000ae3565b92915050565b6200049662000576565b6001600160a01b038116620004c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620004d181620005a5565b50565b60026020526000908152604090208054620004ef906200088a565b80601f01602080910402602001604051908101604052809291908181526020018280546200051d906200088a565b80156200056e5780601f1062000542576101008083540402835291602001916200056e565b820191906000526020600020905b8154815290600101906020018083116200055057829003601f168201915b505050505081565b6000546001600160a01b031633146200040f5760405163118cdaa760e01b8152336004820152602401620004bd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611eb78062000b0883390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200062b57600080fd5b813567ffffffffffffffff8082111562000649576200064962000603565b604051601f8301601f19908116603f0116810190828211818310171562000674576200067462000603565b816040528381528660208588010111156200068e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620006c157600080fd5b813567ffffffffffffffff811115620006d957600080fd5b620006e78482850162000619565b949350505050565b6000602082840312156200070257600080fd5b81356001600160a01b03811681146200071a57600080fd5b9392505050565b60005b838110156200073e57818101518382015260200162000724565b50506000910152565b600081518084526200076181602086016020860162000721565b601f01601f19169290920160200192915050565b6020815260006200071a602083018462000747565b600080600080600060a08688031215620007a357600080fd5b853567ffffffffffffffff80821115620007bc57600080fd5b620007ca89838a0162000619565b96506020880135915080821115620007e157600080fd5b620007ef89838a0162000619565b955060408801359150808211156200080657600080fd5b6200081489838a0162000619565b945060608801359150808211156200082b57600080fd5b6200083989838a0162000619565b935060808801359150808211156200085057600080fd5b506200085f8882890162000619565b9150509295509295909350565b600082516200088081846020870162000721565b9190910192915050565b600181811c908216806200089f57607f821691505b602082108103620008c057634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038716815260c060208201819052600090620008ec9083018862000747565b828103604084015262000900818862000747565b9050828103606084015262000916818762000747565b905082810360808401526200092c818662000747565b905082810360a084015262000942818562000747565b9998505050505050505050565b601f8211156200099f576000816000526020600020601f850160051c810160208610156200097a5750805b601f850160051c820191505b818110156200099b5782815560010162000986565b5050505b505050565b815167ffffffffffffffff811115620009c157620009c162000603565b620009d981620009d284546200088a565b846200094f565b602080601f83116001811462000a115760008415620009f85750858301515b600019600386901b1c1916600185901b1785556200099b565b600085815260208120601f198616915b8281101562000a425788860151825594840194600190910190840162000a21565b508582101562000a615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038616815260a06020820181905260009062000a979083018762000747565b828103604084015262000aab818762000747565b9050828103606084015262000ac1818662000747565b9050828103608084015262000ad7818562000747565b98975050505050505050565b60006020828403121562000af657600080fd5b815180151581146200071a57600080fdfe60806040523480156200001157600080fd5b5060405162001eb738038062001eb7833981016040819052620000349162000202565b858585600062000045838262000386565b50600162000054828262000386565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000cb565b50600c620000a0848262000386565b50600d620000af838262000386565b50600e620000be828262000386565b5050505050505062000452565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200013557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016257600080fd5b81516001600160401b03808211156200017f576200017f6200013a565b604051601f8301601f19908116603f01168101908282118183101715620001aa57620001aa6200013a565b8160405283815260209250866020858801011115620001c857600080fd5b600091505b83821015620001ec5785820183015181830184015290820190620001cd565b6000602085830101528094505050505092915050565b60008060008060008060c087890312156200021c57600080fd5b62000227876200011d565b60208801519096506001600160401b03808211156200024557600080fd5b620002538a838b0162000150565b965060408901519150808211156200026a57600080fd5b620002788a838b0162000150565b955060608901519150808211156200028f57600080fd5b6200029d8a838b0162000150565b94506080890151915080821115620002b457600080fd5b620002c28a838b0162000150565b935060a0890151915080821115620002d957600080fd5b50620002e889828a0162000150565b9150509295509295509295565b600181811c908216806200030a57607f821691505b6020821081036200032b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000381576000816000526020600020601f850160051c810160208610156200035c5750805b601f850160051c820191505b818110156200037d5782815560010162000368565b5050505b505050565b81516001600160401b03811115620003a257620003a26200013a565b620003ba81620003b38454620002f5565b8462000331565b602080601f831160018114620003f25760008415620003d95750858301515b600019600386901b1c1916600185901b1785556200037d565b600085815260208120601f198616915b82811015620004235788860151825594840194600190910190840162000402565b5085821015620004425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b611a5580620004626000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a76b4d56116100a2578063cd279c7c11610071578063cd279c7c146103a8578063e8a3d485146103bb578063e985e9c5146103c3578063f2fde38b146103d657600080fd5b8063a76b4d5614610372578063b49bbd941461037a578063b88d4fde14610382578063c87b56dd1461039557600080fd5b806394e29329116100de57806394e293291461034757806395d89b411461034f578063a159047b14610357578063a22cb4651461035f57600080fd5b806370a082311461031b578063715018a61461032e5780638da5cb5b1461033657600080fd5b80632f745c59116101715780634f558e791161014b5780634f558e79146102c25780634f6ccce7146102ed5780635e0a9661146103005780636352211e1461030857600080fd5b80632f745c591461028957806342842e0e1461029c57806342966c68146102af57600080fd5b8063095ea7b3116101ad578063095ea7b31461023c57806318160ddd1461025157806318e97fd11461026357806323b872dd1461027657600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611494565b6103e9565b60405190151581526020015b60405180910390f35b6102046103fa565b6040516101f39190611501565b61022461021f366004611514565b61048c565b6040516001600160a01b0390911681526020016101f3565b61024f61024a366004611549565b6104b5565b005b6009545b6040519081526020016101f3565b61024f61027136600461161f565b6104c4565b61024f610284366004611666565b6104d6565b610255610297366004611549565b610566565b61024f6102aa366004611666565b6105cb565b61024f6102bd366004611514565b6105eb565b6101e76102d0366004611514565b6000908152600260205260409020546001600160a01b0316151590565b6102556102fb366004611514565b6105f7565b610204610650565b610224610316366004611514565b61065f565b6102556103293660046116a2565b61066a565b61024f6106b2565b600b546001600160a01b0316610224565b6102046106c6565b6102046106d5565b6102046106e4565b61024f61036d3660046116bd565b610772565b61020461077d565b61020461078a565b61024f6103903660046116f9565b610797565b6102046103a3366004611514565b6107ae565b61024f6103b6366004611775565b6107b9565b6102046107d5565b6101e76103d13660046117cc565b6107e4565b61024f6103e43660046116a2565b610812565b60006103f482610850565b92915050565b606060008054610409906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610435906117ff565b80156104825780601f1061045757610100808354040283529160200191610482565b820191906000526020600020905b81548152906001019060200180831161046557829003601f168201915b5050505050905090565b600061049782610875565b506000828152600460205260409020546001600160a01b03166103f4565b6104c08282336108ae565b5050565b6104cc6108bb565b6104c082826108e8565b6001600160a01b03821661050557604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610512838333610938565b9050836001600160a01b0316816001600160a01b031614610560576040516364283d7b60e01b81526001600160a01b03808616600483015260248201849052821660448201526064016104fc565b50505050565b60006105718361066a565b82106105a25760405163295f44f760e21b81526001600160a01b0384166004820152602481018390526044016104fc565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6105e683838360405180602001604052806000815250610797565b505050565b6104c060008233610938565b600061060260095490565b821061062b5760405163295f44f760e21b815260006004820152602481018390526044016104fc565b6009828154811061063e5761063e611839565b90600052602060002001549050919050565b6060600d8054610409906117ff565b60006103f482610875565b60006001600160a01b038216610696576040516322718ad960e21b8152600060048201526024016104fc565b506001600160a01b031660009081526003602052604090205490565b6106ba6108bb565b6106c4600061094d565b565b6060600c8054610409906117ff565b606060018054610409906117ff565b600d80546106f1906117ff565b80601f016020809104026020016040519081016040528092919081815260200182805461071d906117ff565b801561076a5780601f1061073f5761010080835404028352916020019161076a565b820191906000526020600020905b81548152906001019060200180831161074d57829003601f168201915b505050505081565b6104c033838361099f565b600e80546106f1906117ff565b600c80546106f1906117ff565b6107a28484846104d6565b61056084848484610a3e565b60606103f482610b67565b6107c16108bb565b6107cb8383610c70565b6105e682826108e8565b6060600e8054610409906117ff565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61081a6108bb565b6001600160a01b03811661084457604051631e4fbdf760e01b8152600060048201526024016104fc565b61084d8161094d565b50565b60006001600160e01b0319821663780e9d6360e01b14806103f457506103f482610c8a565b6000818152600260205260408120546001600160a01b0316806103f457604051637e27328960e01b8152600481018490526024016104fc565b6105e68383836001610caf565b600b546001600160a01b031633146106c45760405163118cdaa760e01b81523360048201526024016104fc565b6000828152600660205260409020610900828261189f565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b6000610945848484610db5565b949350505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166109d157604051630b61174360e31b81526001600160a01b03831660048201526024016104fc565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561056057604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610a8090339088908790879060040161195f565b6020604051808303816000875af1925050508015610abb575060408051601f3d908101601f19168201909252610ab89181019061199c565b60015b610b24573d808015610ae9576040519150601f19603f3d011682016040523d82523d6000602084013e610aee565b606091505b508051600003610b1c57604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610b6057604051633250574960e11b81526001600160a01b03851660048201526024016104fc565b5050505050565b6060610b7282610875565b5060008281526006602052604081208054610b8c906117ff565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb8906117ff565b8015610c055780601f10610bda57610100808354040283529160200191610c05565b820191906000526020600020905b815481529060010190602001808311610be857829003601f168201915b505050505090506000610c2360408051602081019091526000815290565b90508051600003610c35575092915050565b815115610c67578082604051602001610c4f9291906119b9565b60405160208183030381529060405292505050919050565b61094584610e82565b6104c0828260405180602001604052806000815250610ef7565b60006001600160e01b03198216632483248360e11b14806103f457506103f482610f0e565b8080610cc357506001600160a01b03821615155b15610d85576000610cd384610875565b90506001600160a01b03831615801590610cff5750826001600160a01b0316816001600160a01b031614155b8015610d125750610d1081846107e4565b155b15610d3b5760405163a9fbf51f60e01b81526001600160a01b03841660048201526024016104fc565b8115610d835783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610dc3858585610f5e565b90506001600160a01b038116610e2057610e1b84600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b610e43565b846001600160a01b0316816001600160a01b031614610e4357610e438185611057565b6001600160a01b038516610e5f57610e5a846110e8565b610945565b846001600160a01b0316816001600160a01b031614610945576109458585611197565b6060610e8d82610875565b506000610ea560408051602081019091526000815290565b90506000815111610ec55760405180602001604052806000815250610ef0565b80610ecf846111e7565b604051602001610ee09291906119b9565b6040516020818303038152906040525b9392505050565b610f01838361127a565b6105e66000848484610a3e565b60006001600160e01b031982166380ac58cd60e01b1480610f3f57506001600160e01b03198216635b5e139f60e01b145b806103f457506301ffc9a760e01b6001600160e01b03198316146103f4565b6000828152600260205260408120546001600160a01b0390811690831615610f8b57610f8b8184866112df565b6001600160a01b03811615610fc957610fa8600085600080610caf565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615610ff8576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006110628361066a565b6000838152600860205260409020549091508082146110b5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b6009546000906110fa906001906119e8565b6000838152600a60205260408120546009805493945090928490811061112257611122611839565b90600052602060002001549050806009838154811061114357611143611839565b6000918252602080832090910192909255828152600a9091526040808220849055858252812055600980548061117b5761117b611a09565b6001900381819060005260206000200160009055905550505050565b600060016111a48461066a565b6111ae91906119e8565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b606060006111f483611343565b600101905060008167ffffffffffffffff81111561121457611214611573565b6040519080825280601f01601f19166020018201604052801561123e576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461124857509392505050565b6001600160a01b0382166112a457604051633250574960e11b8152600060048201526024016104fc565b60006112b283836000610938565b90506001600160a01b038116156105e6576040516339e3563760e11b8152600060048201526024016104fc565b6112ea83838361141b565b6105e6576001600160a01b03831661131857604051637e27328960e01b8152600481018290526024016104fc565b60405163177e802f60e01b81526001600160a01b0383166004820152602481018290526044016104fc565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113825772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113ae576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113cc57662386f26fc10000830492506010015b6305f5e10083106113e4576305f5e100830492506008015b61271083106113f857612710830492506004015b6064831061140a576064830492506002015b600a83106103f45760010192915050565b60006001600160a01b038316158015906109455750826001600160a01b0316846001600160a01b03161480611455575061145584846107e4565b806109455750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461084d57600080fd5b6000602082840312156114a657600080fd5b8135610ef08161147e565b60005b838110156114cc5781810151838201526020016114b4565b50506000910152565b600081518084526114ed8160208601602086016114b1565b601f01601f19169290920160200192915050565b602081526000610ef060208301846114d5565b60006020828403121561152657600080fd5b5035919050565b80356001600160a01b038116811461154457600080fd5b919050565b6000806040838503121561155c57600080fd5b6115658361152d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156115a4576115a4611573565b604051601f8501601f19908116603f011681019082821181831017156115cc576115cc611573565b816040528093508581528686860111156115e557600080fd5b858560208301376000602087830101525050509392505050565b600082601f83011261161057600080fd5b610ef083833560208501611589565b6000806040838503121561163257600080fd5b82359150602083013567ffffffffffffffff81111561165057600080fd5b61165c858286016115ff565b9150509250929050565b60008060006060848603121561167b57600080fd5b6116848461152d565b92506116926020850161152d565b9150604084013590509250925092565b6000602082840312156116b457600080fd5b610ef08261152d565b600080604083850312156116d057600080fd5b6116d98361152d565b9150602083013580151581146116ee57600080fd5b809150509250929050565b6000806000806080858703121561170f57600080fd5b6117188561152d565b93506117266020860161152d565b925060408501359150606085013567ffffffffffffffff81111561174957600080fd5b8501601f8101871361175a57600080fd5b61176987823560208401611589565b91505092959194509250565b60008060006060848603121561178a57600080fd5b6117938461152d565b925060208401359150604084013567ffffffffffffffff8111156117b657600080fd5b6117c2868287016115ff565b9150509250925092565b600080604083850312156117df57600080fd5b6117e88361152d565b91506117f66020840161152d565b90509250929050565b600181811c9082168061181357607f821691505b60208210810361183357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f8211156105e6576000816000526020600020601f850160051c810160208610156118785750805b601f850160051c820191505b8181101561189757828155600101611884565b505050505050565b815167ffffffffffffffff8111156118b9576118b9611573565b6118cd816118c784546117ff565b8461184f565b602080601f83116001811461190257600084156118ea5750858301515b600019600386901b1c1916600185901b178555611897565b600085815260208120601f198616915b8281101561193157888601518255948401946001909101908401611912565b508582101561194f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611992908301846114d5565b9695505050505050565b6000602082840312156119ae57600080fd5b8151610ef08161147e565b600083516119cb8184602088016114b1565b8351908301906119df8183602088016114b1565b01949350505050565b818103818111156103f457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212206ff38700c73b602455dbb7964f2d3281f62efc77263f0f3bdb67f5e4ee5d4f3f64736f6c63430008170033a26469706673582212207f55223fc039b168a1e0c0bb9dc8d219b8219d1b2151fe8e9843aecefd41f82664736f6c63430008170033" access(all) let compiledERC721Bytecode = "60806040523480156200001157600080fd5b5033604051806040016040528060048152602001634e414d4560e01b8152506040518060400160405280600681526020016514d6535093d360d21b8152508160009081620000609190620001ac565b5060016200006f8282620001ac565b5050506001600160a01b038116620000a157604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000ac81620000b3565b5062000278565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200013057607f821691505b6020821081036200015157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001a7576000816000526020600020601f850160051c81016020861015620001825750805b601f850160051c820191505b81811015620001a3578281556001016200018e565b5050505b505050565b81516001600160401b03811115620001c857620001c862000105565b620001e081620001d984546200011b565b8462000157565b602080601f831160018114620002185760008415620001ff5750858301515b600019600386901b1c1916600185901b178555620001a3565b600085815260208120601f198616915b82811015620002495788860151825594840194600190910190840162000228565b5085821015620002685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61143080620002886000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063715018a6116100a2578063b88d4fde11610071578063b88d4fde14610239578063c87b56dd1461024c578063cd279c7c1461025f578063e985e9c514610272578063f2fde38b1461028557600080fd5b8063715018a6146102055780638da5cb5b1461020d57806395d89b411461021e578063a22cb4651461022657600080fd5b806323b872dd116100e957806323b872dd1461019857806342842e0e146101ab57806342966c68146101be5780636352211e146101d157806370a08231146101e457600080fd5b806301ffc9a71461011b57806306fdde0314610143578063081812fc14610158578063095ea7b314610183575b600080fd5b61012e610129366004610f0f565b610298565b60405190151581526020015b60405180910390f35b61014b6102a9565b60405161013a9190610f7c565b61016b610166366004610f8f565b61033b565b6040516001600160a01b03909116815260200161013a565b610196610191366004610fc4565b610364565b005b6101966101a6366004610fee565b610373565b6101966101b9366004610fee565b610403565b6101966101cc366004610f8f565b610423565b61016b6101df366004610f8f565b61042f565b6101f76101f236600461102a565b61043a565b60405190815260200161013a565b610196610482565b6007546001600160a01b031661016b565b61014b610496565b610196610234366004611045565b6104a5565b61019661024736600461110d565b6104b0565b61014b61025a366004610f8f565b6104c7565b61019661026d366004611189565b6104d2565b61012e6102803660046111f4565b6104ee565b61019661029336600461102a565b61051c565b60006102a38261055a565b92915050565b6060600080546102b890611227565b80601f01602080910402602001604051908101604052809291908181526020018280546102e490611227565b80156103315780601f1061030657610100808354040283529160200191610331565b820191906000526020600020905b81548152906001019060200180831161031457829003601f168201915b5050505050905090565b60006103468261057f565b506000828152600460205260409020546001600160a01b03166102a3565b61036f8282336105b8565b5050565b6001600160a01b0382166103a257604051633250574960e11b8152600060048201526024015b60405180910390fd5b60006103af8383336105c5565b9050836001600160a01b0316816001600160a01b0316146103fd576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610399565b50505050565b61041e838383604051806020016040528060008152506104b0565b505050565b61036f600082336105c5565b60006102a38261057f565b60006001600160a01b038216610466576040516322718ad960e21b815260006004820152602401610399565b506001600160a01b031660009081526003602052604090205490565b61048a6106be565b61049460006106eb565b565b6060600180546102b890611227565b61036f33838361073d565b6104bb848484610373565b6103fd848484846107dc565b60606102a382610905565b6104da6106be565b6104e48383610a16565b61041e8282610a30565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6105246106be565b6001600160a01b03811661054e57604051631e4fbdf760e01b815260006004820152602401610399565b610557816106eb565b50565b60006001600160e01b03198216632483248360e11b14806102a357506102a382610a80565b6000818152600260205260408120546001600160a01b0316806102a357604051637e27328960e01b815260048101849052602401610399565b61041e8383836001610ad0565b6000828152600260205260408120546001600160a01b03908116908316156105f2576105f2818486610bd6565b6001600160a01b038116156106305761060f600085600080610ad0565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561065f576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6007546001600160a01b031633146104945760405163118cdaa760e01b8152336004820152602401610399565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821661076f57604051630b61174360e31b81526001600160a01b0383166004820152602401610399565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156103fd57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061081e903390889087908790600401611261565b6020604051808303816000875af1925050508015610859575060408051601f3d908101601f191682019092526108569181019061129e565b60015b6108c2573d808015610887576040519150601f19603f3d011682016040523d82523d6000602084013e61088c565b606091505b5080516000036108ba57604051633250574960e11b81526001600160a01b0385166004820152602401610399565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146108fe57604051633250574960e11b81526001600160a01b0385166004820152602401610399565b5050505050565b60606109108261057f565b506000828152600660205260408120805461092a90611227565b80601f016020809104026020016040519081016040528092919081815260200182805461095690611227565b80156109a35780601f10610978576101008083540402835291602001916109a3565b820191906000526020600020905b81548152906001019060200180831161098657829003601f168201915b5050505050905060006109c160408051602081019091526000815290565b905080516000036109d3575092915050565b815115610a055780826040516020016109ed9291906112bb565b60405160208183030381529060405292505050919050565b610a0e84610c3a565b949350505050565b61036f828260405180602001604052806000815250610caf565b6000828152600660205260409020610a48828261133a565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b60006001600160e01b031982166380ac58cd60e01b1480610ab157506001600160e01b03198216635b5e139f60e01b145b806102a357506301ffc9a760e01b6001600160e01b03198316146102a3565b8080610ae457506001600160a01b03821615155b15610ba6576000610af48461057f565b90506001600160a01b03831615801590610b205750826001600160a01b0316816001600160a01b031614155b8015610b335750610b3181846104ee565b155b15610b5c5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610399565b8115610ba45783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b610be1838383610cc6565b61041e576001600160a01b038316610c0f57604051637e27328960e01b815260048101829052602401610399565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610399565b6060610c458261057f565b506000610c5d60408051602081019091526000815290565b90506000815111610c7d5760405180602001604052806000815250610ca8565b80610c8784610d29565b604051602001610c989291906112bb565b6040516020818303038152906040525b9392505050565b610cb98383610dbc565b61041e60008484846107dc565b60006001600160a01b03831615801590610a0e5750826001600160a01b0316846001600160a01b03161480610d005750610d0084846104ee565b80610a0e5750506000908152600460205260409020546001600160a01b03908116911614919050565b60606000610d3683610e21565b600101905060008167ffffffffffffffff811115610d5657610d56611081565b6040519080825280601f01601f191660200182016040528015610d80576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610d8a57509392505050565b6001600160a01b038216610de657604051633250574960e11b815260006004820152602401610399565b6000610df4838360006105c5565b90506001600160a01b0381161561041e576040516339e3563760e11b815260006004820152602401610399565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610e605772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610e8c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610eaa57662386f26fc10000830492506010015b6305f5e1008310610ec2576305f5e100830492506008015b6127108310610ed657612710830492506004015b60648310610ee8576064830492506002015b600a83106102a35760010192915050565b6001600160e01b03198116811461055757600080fd5b600060208284031215610f2157600080fd5b8135610ca881610ef9565b60005b83811015610f47578181015183820152602001610f2f565b50506000910152565b60008151808452610f68816020860160208601610f2c565b601f01601f19169290920160200192915050565b602081526000610ca86020830184610f50565b600060208284031215610fa157600080fd5b5035919050565b80356001600160a01b0381168114610fbf57600080fd5b919050565b60008060408385031215610fd757600080fd5b610fe083610fa8565b946020939093013593505050565b60008060006060848603121561100357600080fd5b61100c84610fa8565b925061101a60208501610fa8565b9150604084013590509250925092565b60006020828403121561103c57600080fd5b610ca882610fa8565b6000806040838503121561105857600080fd5b61106183610fa8565b91506020830135801515811461107657600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156110b2576110b2611081565b604051601f8501601f19908116603f011681019082821181831017156110da576110da611081565b816040528093508581528686860111156110f357600080fd5b858560208301376000602087830101525050509392505050565b6000806000806080858703121561112357600080fd5b61112c85610fa8565b935061113a60208601610fa8565b925060408501359150606085013567ffffffffffffffff81111561115d57600080fd5b8501601f8101871361116e57600080fd5b61117d87823560208401611097565b91505092959194509250565b60008060006060848603121561119e57600080fd5b6111a784610fa8565b925060208401359150604084013567ffffffffffffffff8111156111ca57600080fd5b8401601f810186136111db57600080fd5b6111ea86823560208401611097565b9150509250925092565b6000806040838503121561120757600080fd5b61121083610fa8565b915061121e60208401610fa8565b90509250929050565b600181811c9082168061123b57607f821691505b60208210810361125b57634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061129490830184610f50565b9695505050505050565b6000602082840312156112b057600080fd5b8151610ca881610ef9565b600083516112cd818460208801610f2c565b8351908301906112e1818360208801610f2c565b01949350505050565b601f82111561041e576000816000526020600020601f850160051c810160208610156113135750805b601f850160051c820191505b818110156113325782815560010161131f565b505050505050565b815167ffffffffffffffff81111561135457611354611081565b611368816113628454611227565b846112ea565b602080601f83116001811461139d57600084156113855750858301515b600019600386901b1c1916600185901b178555611332565b600085815260208120601f198616915b828110156113cc578886015182559484019460019091019084016113ad565b50858210156113ea5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea264697066735822122046da1d9cfc7c225e4655204f464e2ecbb316a6284c51c9c338433a1abb5919f864736f6c63430008170033" +access(all) let evmBridgeRouterCode = "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a696d706f72742045564d2066726f6d203078303030303030303030303030303030310a0a696d706f72742049466c6f7745564d4e46544272696467652066726f6d203078303030303030303030303030303030370a0a2f2f2f205468697320636f6e747261637420646566696e65732061206d656368616e69736d20666f7220726f7574696e67206272696467652072657175657374732066726f6d207468652045564d20636f6e747261637420746f2074686520466c6f772d45564d206272696467652061732077656c6c0a2f2f2f206173207570646174696e67207468652064657369676e617465642062726964676520616464726573730a2f2f2f0a61636365737328616c6c290a636f6e74726163742045564d427269646765526f75746572207b0a0a202020202f2f2f20456e7469746c656d656e7420616c6c6f77696e6720666f72207570646174657320746f2074686520526f757465720a2020202061636365737328616c6c2920656e7469746c656d656e7420526f7574657241646d696e0a0a202020202f2f2f20456d69747465642069662f7768656e207468652062726964676520636f6e74726163742074686520726f75746572206469726563747320746f20697320757064617465640a2020202061636365737328616c6c29206576656e7420427269646765436f6e74726163745570646174656428616464726573733a20416464726573732c206e616d653a20537472696e67290a202020200a202020202f2f2f204272696467654163636573736f7220696d706c656d656e746174696f6e2075736564206279207468652045564d20636f6e747261637420746f20726f757465206272696467652063616c6c73206265747765656e20564d730a202020202f2f2f0a2020202061636365737328616c6c290a202020207265736f7572636520526f75746572203a2045564d2e4272696467654163636573736f72207b0a20202020202020202f2f2f2041646472657373206f66207468652062726964676520636f6e74726163740a202020202020202061636365737328616c6c292076617220627269646765416464726573733a20416464726573730a20202020202020202f2f2f204e616d65206f66207468652062726964676520636f6e74726163740a202020202020202061636365737328616c6c292076617220627269646765436f6e74726163744e616d653a20537472696e670a0a2020202020202020696e697428616464726573733a20416464726573732c206e616d653a20537472696e6729207b0a20202020202020202020202073656c662e62726964676541646472657373203d20616464726573730a20202020202020202020202073656c662e627269646765436f6e74726163744e616d65203d206e616d650a20202020202020207d0a0a20202020202020202f2f2f2050617373657320616c6f6e672074686520627269646765207265717565737420746f206465646963617465642062726964676520636f6e74726163740a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d206e66743a20546865204e465420746f206265206272696467656420746f2045564d0a20202020202020202f2f2f2040706172616d20746f3a205468652061646472657373206f66207468652045564d206163636f756e7420746f2072656365697665207468652062726964676564204e46540a20202020202020202f2f2f2040706172616d2066656550726f76696465723a2041207265666572656e636520746f20612046756e6769626c65546f6b656e2050726f76696465722066726f6d20776869636820746865206272696467696e67206665652069732077697468647261776e20696e2024464c4f570a20202020202020202f2f2f0a20202020202020206163636573732845564d2e427269646765290a202020202020202066756e206465706f7369744e4654280a2020202020202020202020206e66743a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d2c0a202020202020202020202020746f3a2045564d2e45564d416464726573732c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a202020202020202029207b0a20202020202020202020202073656c662e626f72726f7742726964676528292e6272696467654e4654546f45564d28746f6b656e3a203c2d6e66742c20746f3a20746f2c2066656550726f76696465723a2066656550726f7669646572290a20202020202020207d0a0a20202020202020202f2f2f2050617373657320616c6f6e672074686520627269646765207265717565737420746f20746865206465646963617465642062726964676520636f6e74726163742c2072657475726e696e67207468652062726964676564204e46540a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d2063616c6c65723a2041207265666572656e636520746f2074686520434f412077686963682063757272656e746c79206f776e7320746865204e465420696e2045564d0a20202020202020202f2f2f2040706172616d20747970653a2054686520436164656e63652074797065206f6620746865204e465420746f20626520627269646765642066726f6d2045564d0a20202020202020202f2f2f2040706172616d2069643a20546865204944206f6620746865204e465420746f20626520627269646765642066726f6d2045564d0a20202020202020202f2f2f2040706172616d2066656550726f76696465723a2041207265666572656e636520746f20612046756e6769626c65546f6b656e2050726f76696465722066726f6d20776869636820746865206272696467696e67206665652069732077697468647261776e20696e2024464c4f570a20202020202020202f2f2f0a20202020202020202f2f2f204072657475726e205468652062726964676564204e46540a20202020202020202f2f2f0a20202020202020206163636573732845564d2e427269646765290a202020202020202066756e2077697468647261774e4654280a20202020202020202020202063616c6c65723a20617574682845564d2e43616c6c29202645564d2e436164656e63654f776e65644163636f756e742c0a202020202020202020202020747970653a20547970652c0a20202020202020202020202069643a2055496e743235362c0a20202020202020202020202066656550726f76696465723a20617574682846756e6769626c65546f6b656e2e57697468647261772920267b46756e6769626c65546f6b656e2e50726f76696465727d0a2020202020202020293a20407b4e6f6e46756e6769626c65546f6b656e2e4e46547d207b0a2020202020202020202020206c657420627269646765203d2073656c662e626f72726f7742726964676528290a2020202020202020202020202f2f20446566696e6520612063616c6c6261636b2066756e6374696f6e2c20656e61626c696e67207468652062726964676520746f20616374206f6e2074686520657068656d6572616c20434f41207265666572656e636520696e2073636f70650a202020202020202020202020766172206578656375746564203d2066616c73650a20202020202020202020202066756e2063616c6c6261636b28293a2045564d2e526573756c74207b0a20202020202020202020202020202020707265207b0a20202020202020202020202020202020202020202165786563757465643a202243616c6c6261636b2063616e206f6e6c79206265206578656375746564206f6e6365220a202020202020202020202020202020207d0a20202020202020202020202020202020706f7374207b0a202020202020202020202020202020202020202065786563757465643a202243616c6c6261636b206d757374206265206578656375746564220a202020202020202020202020202020207d0a202020202020202020202020202020206578656375746564203d20747275650a2020202020202020202020202020202072657475726e2063616c6c65722e63616c6c280a2020202020202020202020202020202020202020746f3a206272696467652e6765744173736f63696174656445564d4164647265737328776974683a2074797065290a2020202020202020202020202020202020202020202020203f3f2070616e696328224e6f2045564d2061646472657373206173736f6369617465642077697468207479706522292c0a2020202020202020202020202020202020202020646174613a2045564d2e656e636f6465414249576974685369676e6174757265280a20202020202020202020202020202020202020202020202022736166655472616e7366657246726f6d28616464726573732c616464726573732c75696e7432353629222c0a2020202020202020202020202020202020202020202020205b63616c6c65722e6164647265737328292c206272696467652e676574427269646765434f4145564d4164647265737328292c2069645d0a2020202020202020202020202020202020202020292c0a20202020202020202020202020202020202020206761734c696d69743a2031353030303030302c0a202020202020202020202020202020202020202076616c75653a2045564d2e42616c616e6365286174746f666c6f773a2030290a20202020202020202020202020202020290a2020202020202020202020207d0a2020202020202020202020202f2f2045786563757465207468652062726964676520726571756573740a20202020202020202020202072657475726e203c2d206272696467652e6272696467654e465446726f6d45564d280a202020202020202020202020202020206f776e65723a2063616c6c65722e6164647265737328292c0a20202020202020202020202020202020747970653a20747970652c0a2020202020202020202020202020202069643a2069642c0a2020202020202020202020202020202066656550726f76696465723a2066656550726f76696465722c0a2020202020202020202020202020202070726f7465637465645472616e7366657243616c6c3a2063616c6c6261636b0a202020202020202020202020290a20202020202020207d0a0a20202020202020202f2f2f2053657473207468652062726964676520636f6e74726163742074686520726f75746572206469726563747320627269646765207265717565737473207468726f7567680a20202020202020202f2f2f0a202020202020202061636365737328526f7574657241646d696e292066756e20736574427269646765436f6e747261637428616464726573733a20416464726573732c206e616d653a20537472696e6729207b0a20202020202020202020202073656c662e62726964676541646472657373203d20616464726573730a20202020202020202020202073656c662e627269646765436f6e74726163744e616d65203d206e616d650a202020202020202020202020656d697420427269646765436f6e74726163745570646174656428616464726573733a20616464726573732c206e616d653a206e616d65290a20202020202020207d0a0a20202020202020202f2f2f2052657475726e732061207265666572656e636520746f207468652062726964676520636f6e74726163740a20202020202020202f2f2f0a20202020202020206163636573732873656c66292066756e20626f72726f7742726964676528293a20267b49466c6f7745564d4e46544272696467657d207b0a20202020202020202020202072657475726e206765744163636f756e742873656c662e62726964676541646472657373292e636f6e7472616374732e626f72726f773c267b49466c6f7745564d4e46544272696467657d3e286e616d653a2073656c662e627269646765436f6e74726163744e616d65290a202020202020202020202020202020203f3f2070616e6963282242726964676520636f6e7472616374206e6f7420666f756e6422290a20202020202020207d0a202020207d0a0a20202020696e697428627269646765416464726573733a20416464726573732c20627269646765436f6e74726163744e616d653a20537472696e6729207b0a202020202020202073656c662e6163636f756e742e73746f726167652e73617665280a2020202020202020202020203c2d63726561746520526f7574657228616464726573733a20627269646765416464726573732c206e616d653a20627269646765436f6e74726163744e616d65292c0a202020202020202020202020746f3a202f73746f726167652f65766d427269646765526f757465720a2020202020202020290a202020207d0a7d0a" + access(all) let bridgedNFTCodeChunks = [ "696d706f7274204e6f6e46756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030310a696d706f7274204d6574616461746156696577732066726f6d203078303030303030303030303030303030310a696d706f727420566965775265736f6c7665722066726f6d203078303030303030303030303030303030310a696d706f72742046756e6769626c65546f6b656e2066726f6d203078303030303030303030303030303030320a696d706f727420466c6f77546f6b656e2066726f6d203078303030303030303030303030303030330a0a696d706f72742045564d2066726f6d203078303030303030303030303030303030310a0a696d706f7274204943726f7373564d2066726f6d203078303030303030303030303030303030370a696d706f7274204945564d4272696467654e46544d696e7465722066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467654e4654457363726f772066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d427269646765436f6e6669672066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467655574696c732066726f6d203078303030303030303030303030303030370a696d706f727420466c6f7745564d4272696467652066726f6d203078303030303030303030303030303030370a696d706f72742043726f7373564d4e46542066726f6d203078303030303030303030303030303030370a0a2f2f2f205468697320636f6e747261637420697320612074656d706c617465207573656420627920466c6f7745564d42726964676520746f20646566696e652045564d2d6e6174697665204e46547320627269646765642066726f6d20466c6f772045564d20746f20466c6f772e0a2f2f2f2055706f6e206465706c6f796d656e74206f66207468697320636f6e74726163742c2074686520636f6e7472616374206e616d65206973206465726976656420617320612066756e6374696f6e206f6620746865206173736574207479706520286865726520616e2045524337323120616b610a2f2f2f20616e204e46542920616e642074686520636f6e747261637427732045564d20616464726573732e20546865206465726976656420636f6e7472616374206e616d65206973207468656e206a6f696e65642077697468207468697320636f6e7472616374277320636f64652c0a2f2f2f207072657061726564206173206368756e6b7320696e20466c6f7745564d42726964676554656d706c61746573206265666f7265206265696e67206465706c6f79656420746f2074686520466c6f772045564d20427269646765206163636f756e742e0a2f2f2f0a2f2f2f204f6e206272696467696e672c2074686520455243373231206973207472616e7366657272656420746f2074686520627269646765277320436164656e63654f776e65644163636f756e742045564d206164647265737320616e642061206e6577204e4654206973206d696e7465642066726f6d0a2f2f2f207468697320636f6e747261637420746f20746865206272696467696e672063616c6c65722e204f6e2072657475726e20746f20466c6f772045564d2c2074686520726576657273652070726f6365737320697320666f6c6c6f776564202d2074686520746f6b656e206973206275726e65640a2f2f2f20696e207468697320636f6e747261637420616e642074686520455243373231206973207472616e7366657272656420746f2074686520646566696e656420726563697069656e742e20496e2074686973207761792c2074686520436164656e636520746f6b656e206163747320617320610a2f2f2f20726570726573656e746174696f6e206f6620626f7468207468652045564d204e465420616e642074687573206f776e6572736869702072696768747320746f2069742075706f6e206272696467696e67206261636b20746f20466c6f772045564d2e0a2f2f2f0a2f2f2f20546f20627269646765206265747765656e20564d732c20612063616c6c65722063616e20656974686572207573652074686520636f6e7472616374206d6574686f647320646566696e65642062656c6f772c206f72207573652074686520466c6f7745564d42726964676527730a2f2f2f206272696467696e67206d6574686f64732077686963682077696c6c2070726f6772616d61746963616c6c7920726f757465206272696467696e672063616c6c7320746f207468697320636f6e74726163742e0a2f2f2f0a2f2f20544f444f3a20496d706c656d656e74204e465420636f6e747261637420696e74657266616365206f6e636520763220617661696c61626c65206c6f63616c6c790a61636365737328616c6c2920636f6e747261637420", "203a204943726f7373564d2c204945564d4272696467654e46544d696e7465722c204e6f6e46756e6769626c65546f6b656e207b0a0a202020202f2f2f20506f696e74657220746f2074686520466163746f7279206465706c6f79656420536f6c696469747920636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365740a2020202061636365737328616c6c29206c65742065766d4e4654436f6e7472616374416464726573733a2045564d2e45564d416464726573730a202020202f2f2f20506f696e74657220746f2074686520466c6f77204e465420636f6e7472616374206164647265737320646566696e696e672074686520627269646765642061737365742c207468697320636f6e7472616374206164647265737320696e207468697320636173650a2020202061636365737328616c6c29206c657420666c6f774e4654436f6e7472616374416464726573733a20416464726573730a202020202f2f2f204e616d65206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c6574206e616d653a20537472696e670a202020202f2f2f2053796d626f6c206f6620746865204e465420636f6c6c656374696f6e20646566696e656420696e2074686520636f72726573706f6e64696e672045524337323120636f6e74726163740a2020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a202020202f2f2f20555249206f662074686520636f6e74726163742c20696620617661696c61626c6520617320612076617220696e2063617365207468652062726964676520656e61626c65732063726f73732d564d204d657461646174612073796e63696e6720696e20746865206675747572650a2020202061636365737328616c6c292076617220636f6e74726163745552493a20537472696e673f0a202020202f2f2f2052657461696e206120436f6c6c656374696f6e20746f207265666572656e6365207768656e207265736f6c76696e6720436f6c6c656374696f6e204d657461646174610a202020206163636573732873656c6629206c657420636f6c6c656374696f6e3a2040436f6c6c656374696f6e0a202020202f2f2f204d617070696e67206f6620746f6b656e205552497320696e6465786564206f6e207468656972204552433732312049442e205468697320776f756c64206e6f74206e6f726d616c6c792062652072657461696e65642077697468696e206120436164656e6365204e46540a202020202f2f2f20636f6e74726163742c206275742073696e6365204e4654206d65746164617461206d6179206265207570646174656420696e2045564d2c20697427732072657461696e6564206865726520736f207468617420746865206272696467652063616e207570646174650a202020202f2f2f20697420616761696e73742074686520736f757263652045524337323120636f6e7472616374207768696368206973207472656174656420617320746865204e4654277320736f75726365206f662074727574682e0a2020202061636365737328616c6c29206c657420746f6b656e555249733a207b55496e743235363a20537472696e677d0a0a202020202f2f2f20546865204e4654207265736f7572636520726570726573656e74696e672074686520627269646765642045524337323120746f6b656e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f75726365204e46543a2043726f7373564d4e46542e45564d4e4654207b0a20202020202020202f2f2f2054686520436164656e6365204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742069643a2055496e7436340a20202020202020202f2f2f2054686520455243373231204944206f6620746865204e46540a202020202020202061636365737328616c6c29206c65742065766d49443a2055496e743235360a20202020202020202f2f2f20546865206e616d65206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c6574206e616d653a20537472696e670a20202020202020202f2f2f205468652073796d626f6c206f6620746865204e465420617320646566696e656420696e207468652045524337323120636f6e74726163740a202020202020202061636365737328616c6c29206c65742073796d626f6c3a20537472696e670a20202020202020202f2f2f204164646974696f6e616c206f6e636861696e206d657461646174610a202020202020202061636365737328616c6c29206c6574206d657461646174613a207b537472696e673a20416e795374727563747d0a0a2020202020202020696e6974280a2020202020202020202020206e616d653a20537472696e672c0a20202020202020202020202073796d626f6c3a20537472696e672c0a20202020202020202020202065766d49443a2055496e743235362c0a2020202020202020202020206d657461646174613a207b537472696e673a20416e795374727563747d0a202020202020202029207b0a20202020202020202020202073656c662e6e616d65203d206e616d650a20202020202020202020202073656c662e73796d626f6c203d2073796d626f6c0a20202020202020202020202073656c662e6964203d2073656c662e757569640a20202020202020202020202073656c662e65766d4944203d2065766d49440a20202020202020202020202073656c662e6d65746164617461203d206d657461646174610a20202020202020207d0a0a20202020202020202f2f2f2052657475726e7320746865206d65746164617461207669657720747970657320737570706f727465642062792074686973204e46540a202020202020202061636365737328616c6c2920766965772066756e20676574566965777328293a205b547970655d207b0a20202020202020202020202072657475726e205b0a20202020202020202020202020202020547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e53657269616c3e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28292c0a20202020202020202020202020202020547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446973706c61793e28290a2020202020202020202020205d0a20202020202020207d0a0a20202020202020202f2f2f205265736f6c7665732061206d65746164617461207669657720666f722074686973204e46540a202020202020202061636365737328616c6c292066756e207265736f6c766556696577285f20766965773a2054797065293a20416e795374727563743f207b0a2020202020202020202020207377697463682076696577207b0a202020202020202020202020202020202f2f20576520646f6e2774206b6e6f772077686174206b696e64206f662066696c65207468652055524920726570726573656e747320284950465320762048545450292c20736f2077652063616e2774207265736f6c766520446973706c617920766965770a202020202020202020202020202020202f2f20776974682074686520555249206173207468756d626e61696c202d207765206d61792061206e6577207374616e64617264207669657720666f722045564d204e465473202d207468697320697320696e746572696d0a202020202020202020202020202020206361736520547970653c43726f7373564d4e46542e45564d427269646765644d657461646174613e28293a0a202020202020202020202020202020202020202072657475726e2043726f7373564d4e46542e45564d427269646765644d65746164617461280a2020202020202020202020202020202020202020202020206e616d653a2073656c662e6e616d652c0a20202020202020202020202020202020202020202020202073796d626f6c3a2073656c662e73796d626f6c2c0a2020202020202020202020202020202020202020202020207572693a2043726f7373564d4e46542e55524928626173655552493a206e696c2c2076616c75653a2073656c662e746f6b656e5552492829290a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e53657269616c3e28293a0a202020202020202020202020202020202020202072657475726e204d6574616461746156696577732e53657269616c280a20202020202020202020202020202020202020202020202073656c662e69640a2020202020202020202020202020202020202020290a202020202020202020202020202020206361736520547970653c4d6574616461746156696577732e4e4654436f6c6c656374696f6e446174613e28293a0a202020202020202020202020202020202020202072657475726e20", @@ -46,7 +52,12 @@ fun getCompiledERC721Bytecode(): String { return compiledERC721Bytecode } +access(all) +fun getEVMBridgeRouterCode(): String { + return evmBridgeRouterCode +} + access(all) fun getBridgedNFTCodeChunks(): [String] { return bridgedNFTCodeChunks -} \ No newline at end of file +} diff --git a/cadence/transactions/test/add_contract.cdc b/cadence/transactions/test/add_contract.cdc new file mode 100644 index 00000000..a9faa2a4 --- /dev/null +++ b/cadence/transactions/test/add_contract.cdc @@ -0,0 +1,5 @@ +transaction(name: String, codeHex: String, arg0: AnyStruct, arg1: AnyStruct) { + prepare(signer: auth(AddContract) &Account) { + signer.contracts.add(name: name, code: codeHex.decodeHex(), arg0, arg1) + } +} \ No newline at end of file diff --git a/flow.json b/flow.json index 5c80d499..aada8935 100644 --- a/flow.json +++ b/flow.json @@ -39,7 +39,7 @@ "source": "./cadence/contracts/bridge/EVMBridgeRouter.cdc", "aliases": { "emulator": "f8d6e0586b0a20c7", - "testing": "0000000000000007" + "testing": "0000000000000001" } }, "EVMDeployer": { From e87a628ac9b72a30bf37a3d6c625f935c3164e29 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:46:13 -0500 Subject: [PATCH 37/39] update test comments --- cadence/tests/flow_evm_bridge_tests.cdc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index e2571875..d3383c22 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -153,7 +153,15 @@ fun setup() { serviceAccount ) Test.expect(updateResult, Test.beSucceeded()) + // TODO: Remove once issue is address - added here for validation Test.assertEqual(true, getAccount(serviceAccount.address).contracts.names.contains("EVMBridgeRouter")) + // This also fails with I.Test.Test.Error(message: "could not find an account with address: 0000000000000001") + // err = Test.deployContract( + // name: "EVMBridgeRouter", + // path: "../contracts/bridge/EVMBridgeRouter.cdc", + // arguments: [] + // ) + // Test.expect(err, Test.beNil()) // Transfer ERC721 deployer some $FLOW let fundERC721AccountResult = executeTransaction( From ec075421de285653bdf46edbe9bfab433d62e047 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 28 Mar 2024 16:53:17 +0200 Subject: [PATCH 38/39] Fix deployment of EVMBridgeRouter on service account --- .../test/is_bridge_router_configured.cdc | 14 +++++++++++++ cadence/tests/flow_evm_bridge_tests.cdc | 20 +++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 cadence/scripts/test/is_bridge_router_configured.cdc diff --git a/cadence/scripts/test/is_bridge_router_configured.cdc b/cadence/scripts/test/is_bridge_router_configured.cdc new file mode 100644 index 00000000..eed254f1 --- /dev/null +++ b/cadence/scripts/test/is_bridge_router_configured.cdc @@ -0,0 +1,14 @@ +import "EVMBridgeRouter" + +access(all) +fun main(): Bool { + let serviceAccount = getAuthAccount(0x0000000000000001) + let router = serviceAccount.storage.borrow<&EVMBridgeRouter.Router>( + from: /storage/evmBridgeRouter + ) ?? panic("Could not borrow Router") + + assert(router.bridgeAddress == 0x0000000000000007) + assert(router.bridgeContractName == "FlowEVMBridge") + + return true +} diff --git a/cadence/tests/flow_evm_bridge_tests.cdc b/cadence/tests/flow_evm_bridge_tests.cdc index d3383c22..45e33782 100644 --- a/cadence/tests/flow_evm_bridge_tests.cdc +++ b/cadence/tests/flow_evm_bridge_tests.cdc @@ -146,22 +146,12 @@ fun setup() { ) Test.expect(err, Test.beNil()) - // Deploy EVMBridgeRouter manually to service account for COA -> bridge integration - let deployResult = executeTransaction( - "../transactions/test/add_contract.cdc", - ["EVMBridgeRouter", getEVMBridgeRouterCode(), bridgeAccount.address, "FlowEVMBridge"], - serviceAccount + err = Test.deployContract( + name: "EVMBridgeRouter", + path: "../contracts/bridge/EVMBridgeRouter.cdc", + arguments: [bridgeAccount.address, "FlowEVMBridge"] ) - Test.expect(updateResult, Test.beSucceeded()) - // TODO: Remove once issue is address - added here for validation - Test.assertEqual(true, getAccount(serviceAccount.address).contracts.names.contains("EVMBridgeRouter")) - // This also fails with I.Test.Test.Error(message: "could not find an account with address: 0000000000000001") - // err = Test.deployContract( - // name: "EVMBridgeRouter", - // path: "../contracts/bridge/EVMBridgeRouter.cdc", - // arguments: [] - // ) - // Test.expect(err, Test.beNil()) + Test.expect(err, Test.beNil()) // Transfer ERC721 deployer some $FLOW let fundERC721AccountResult = executeTransaction( From 2dbe4e184ae2bbc3807d4ba35776c373c88248a6 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Fri, 29 Mar 2024 14:22:49 +0200 Subject: [PATCH 39/39] Update flow-cli version used in CI workflow --- .github/workflows/cadence_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml index ee4a3111..bee6bf5a 100644 --- a/.github/workflows/cadence_test.yml +++ b/.github/workflows/cadence_test.yml @@ -19,7 +19,7 @@ jobs: restore-keys: | ${{ runner.os }}-go- - name: Install Flow CLI - run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.15.0-cadence-v1.0.0-preview.12 + run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.15.0-cadence-v1.0.0-preview.14 - name: Flow CLI Version run: flow version - name: Update PATH