From 9eab72160a6feea85076cdcd8b91b80bddf9cbd2 Mon Sep 17 00:00:00 2001 From: shab Date: Thu, 23 May 2024 22:12:46 -0400 Subject: [PATCH 01/65] wip cw1155 pointer --- .gitignore | 1 + example/cosmwasm/cw1155/Cargo.lock | 986 ++++++++++++++++++ example/cosmwasm/cw1155/Cargo.toml | 27 + .../cosmwasm/cw1155/artifacts/checksums.txt | 1 + .../artifacts/checksums_intermediate.txt | 1 + .../cw1155/artifacts/cwerc1155-aarch64.wasm | Bin 0 -> 291992 bytes example/cosmwasm/cw1155/src/contract.rs | 471 +++++++++ example/cosmwasm/cw1155/src/error.rs | 11 + example/cosmwasm/cw1155/src/lib.rs | 5 + example/cosmwasm/cw1155/src/msg.rs | 200 ++++ example/cosmwasm/cw1155/src/querier.rs | 177 ++++ example/cosmwasm/cw1155/src/state.rs | 3 + 12 files changed, 1883 insertions(+) create mode 100644 example/cosmwasm/cw1155/Cargo.lock create mode 100644 example/cosmwasm/cw1155/Cargo.toml create mode 100644 example/cosmwasm/cw1155/artifacts/checksums.txt create mode 100644 example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt create mode 100644 example/cosmwasm/cw1155/artifacts/cwerc1155-aarch64.wasm create mode 100644 example/cosmwasm/cw1155/src/contract.rs create mode 100644 example/cosmwasm/cw1155/src/error.rs create mode 100644 example/cosmwasm/cw1155/src/lib.rs create mode 100644 example/cosmwasm/cw1155/src/msg.rs create mode 100644 example/cosmwasm/cw1155/src/querier.rs create mode 100644 example/cosmwasm/cw1155/src/state.rs diff --git a/.gitignore b/.gitignore index ada3dc4f6..726efd06f 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ coverage.out example/cosmwasm/echo/target example/cosmwasm/cw20/target example/cosmwasm/cw721/target +example/cosmwasm/cw1155/target # Solidity contracts artifacts contracts/artifacts diff --git a/example/cosmwasm/cw1155/Cargo.lock b/example/cosmwasm/cw1155/Cargo.lock new file mode 100644 index 000000000..19f2d7833 --- /dev/null +++ b/example/cosmwasm/cw1155/Cargo.lock @@ -0,0 +1,986 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bnum" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cosmwasm-crypto" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" +dependencies = [ + "digest 0.10.7", + "ecdsa", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40abec852f3d4abec6d44ead9a58b78325021a1ead1e7229c3471414e57b2e49" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b166215fbfe93dc5575bae062aa57ae7bb41121cffe53bac33b033257949d2a9" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf12f8e20bb29d1db66b7ca590bc2f670b548d21e9be92499bc0f9022a994a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad011ae7447188e26e4a7dbca2fcd0fc186aa21ae5c86df0503ea44c78f9e469" +dependencies = [ + "base64", + "bech32", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-address-like" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451a4691083a88a3c0630a8a88799e9d4cd6679b7ce8ff22b8da2873ff31d380" +dependencies = [ + "cosmwasm-std", +] + +[[package]] +name = "cw-ownable" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093dfb4520c48b5848274dd88ea99e280a04bc08729603341c7fb0d758c74321" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like", + "cw-ownable-derive", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "thiserror", +] + +[[package]] +name = "cw-ownable-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d3bf2e0f341bb6cc100d7d441d31cf713fbd3ce0c511f91e79f14b40a889af" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-storage-plus" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.16.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw-utils" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 1.1.2", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw1155" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw1155-base" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw1155", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "schemars", + "serde", +] + +[[package]] +name = "cw1155-royalties" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-std", + "cw1155", + "cw1155-base", + "cw2 1.1.2", + "cw2981-royalties 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "schemars", + "serde", +] + +[[package]] +name = "cw2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2981-royalties" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985cdd5d304fb37ff16c2538f4d8f12a264af6526b967e066c6bb6972d60ab92" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw2981-royalties" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a1ea6e6277bdd6dfc043a9b1380697fe29d6e24b072597439523658d21d791" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "schemars", + "serde", +] + +[[package]] +name = "cw721" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c4d286625ccadc957fe480dd3bdc54ada19e0e6b5b9325379db3130569e914" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.3", + "schemars", + "serde", +] + +[[package]] +name = "cw721" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.3", + "schemars", + "serde", +] + +[[package]] +name = "cw721-base" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77518e27431d43214cff4cdfbd788a7508f68d9b1f32389e6fce513e7eaccbef" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw721 0.16.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da518d9f68bfda7d972cbaca2e8fcf04651d0edc3de72b04ae2bcd9289c81614" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.16.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.18.0" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721-base 0.16.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cwerc1155" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "cw1155", + "cw1155-royalties", + "cw2981-royalties 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.8", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/example/cosmwasm/cw1155/Cargo.toml b/example/cosmwasm/cw1155/Cargo.toml new file mode 100644 index 000000000..d172eb9c2 --- /dev/null +++ b/example/cosmwasm/cw1155/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "cwerc1155" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-schema = "1.5.0" +cosmwasm-std = { version = "1.3.1", features = ["staking", "stargate"] } +cw-storage-plus = "1.2.0" +cw1155-royalties = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "cfa0c08" } +cw1155 = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "cfa0c08" } +cw2981-royalties = "0.18.0" +cw721 = "0.18.0" +cw721-base = "0.18.0" +schemars = "0.8.16" +serde = "1.0.195" +thiserror = "1.0.56" \ No newline at end of file diff --git a/example/cosmwasm/cw1155/artifacts/checksums.txt b/example/cosmwasm/cw1155/artifacts/checksums.txt new file mode 100644 index 000000000..ddaed5356 --- /dev/null +++ b/example/cosmwasm/cw1155/artifacts/checksums.txt @@ -0,0 +1 @@ +3ec5c08215a37ebd3bb5905cda377243b0946cecdc440d91bb11447e823da21d cwerc1155-aarch64.wasm diff --git a/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt b/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt new file mode 100644 index 000000000..bb4b3c1c8 --- /dev/null +++ b/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt @@ -0,0 +1 @@ +64e02d4e121693160aa8b9f08594807a98d24d64be1b84015c564cc59d0b6652 ./target/wasm32-unknown-unknown/release/cwerc1155.wasm diff --git a/example/cosmwasm/cw1155/artifacts/cwerc1155-aarch64.wasm b/example/cosmwasm/cw1155/artifacts/cwerc1155-aarch64.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a905d5e616d419c5a8cc58396b969e0c0536b327 GIT binary patch literal 291992 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

L7&* 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ⓈgN@1^WSP;)LOB;F>qdk}IDvdpvkjTjtf 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 Result { + ERC1155_ADDRESS.save(deps.storage, &msg.erc1155_address)?; + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: Cw1155RoyaltiesExecuteMsg, +) -> Result, ContractError> { + match msg { + Cw1155RoyaltiesExecuteMsg::Send { from, to, token_id , amount, msg } => { + execute_send_single(deps, info, from, to, token_id, amount, msg) + }, + Cw1155RoyaltiesExecuteMsg::SendBatch { from, to, batch, msg } => { + execute_send_batch(deps, info, from, to, batch, msg) + } + Cw1155RoyaltiesExecuteMsg::Approve { spender, token_id, amount, expires: _ } => { + execute_approve(deps, info, spender, token_id, true) + }, + Cw1155RoyaltiesExecuteMsg::Revoke { spender, token_id, amount } => { + execute_approve(deps, info, spender, token_id, false) + }, + Cw1155RoyaltiesExecuteMsg::ApproveAll { operator, expires: _ } => { + execute_approve_all(deps, info, operator, true) + }, + Cw1155RoyaltiesExecuteMsg::RevokeAll { operator } => { + execute_approve_all(deps, info, operator, false) + }, + Cw1155RoyaltiesExecuteMsg::Burn { .. } => { execute_burn() }, + Cw1155RoyaltiesExecuteMsg::BurnBatch { .. } => { execute_burn_batch() }, + Cw1155RoyaltiesExecuteMsg::Mint { .. } => execute_mint(), + Cw1155RoyaltiesExecuteMsg::MintBatch { .. } => execute_mint_batch(), + Cw1155RoyaltiesExecuteMsg::UpdateOwnership(_) => update_ownership(), + Cw1155RoyaltiesExecuteMsg::Extension { .. } => execute_extension(), + } +} + +pub fn execute_send_single( + deps: DepsMut, + info: MessageInfo, + from: Option, + recipient: String, + token_id: String, + amount: Uint128, + msg: Option, +) -> Result, ContractError> { + // validate recipient + let recipient = deps.api.addr_validate(&recipient)?; + + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + + let querier = EvmQuerier::new(&deps.querier); + let payload = querier.erc1155_transfer_single_payload(from.clone().unwrap_or_else(|| info.sender.to_string()), recipient.to_string(), token_id.to_string(), amount)?; + let delegate_msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; + + let mut res = Response::new().add_message(delegate_msg); + + if let Some(msg) = msg { + let send = Cw1155ReceiveMsg { + operator: info.sender.to_string(), + from, + token_id: token_id.to_string(), + amount, + msg, + }; + res = res + .add_message(send.into_cosmos_msg(recipient.to_string())?) + .add_attribute("action", "send_single"); + } else { + res = res.add_attribute("action", "transfer_single") + } + + res = res.add_attribute("sender", info.sender) + .add_attribute("recipient", recipient) + .add_attribute("token_id", token_id) + .add_attribute("amount", amount); + Ok(res) +} + +pub fn execute_send_batch( + deps: DepsMut, + info: MessageInfo, + from: Option, + recipient: String, + batch: Vec, + msg: Option, +) -> Result, ContractError> { + // validate recipient + let recipient = deps.api.addr_validate(&recipient)?; + + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + + let token_ids = batch.to_vec().into_iter().map(|t| t.token_id).collect::>(); + let amounts = batch.to_vec().into_iter().map(|t| t.amount).collect::>(); + + let querier = EvmQuerier::new(&deps.querier); + let payload = querier.erc1155_transfer_batch_payload(from.clone().unwrap_or_else(|| info.sender.to_string()), recipient.to_string(), token_ids.to_vec(), amounts.to_vec())?; + let delegate_msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; + + let mut res = Response::new().add_message(delegate_msg); + + if let Some(msg) = msg { + let send = Cw1155BatchReceiveMsg { + operator: info.sender.to_string(), + from, + batch, + msg, + }; + res = res + .add_message(send.into_cosmos_msg(recipient.to_string())?) + .add_attribute("action", "send_batch"); + } else { + res = res.add_attribute("action", "transfer_batch") + } + + res = res.add_attribute("sender", info.sender) + .add_attribute("recipient", recipient) + .add_attribute("token_ids", token_ids.join(",")) + .add_attribute("amounts", amounts.iter().map(|a| a.to_string()).collect::>().join(",")); + Ok(res) +} + +pub fn execute_approve( + deps: DepsMut, + info: MessageInfo, + spender: String, + token_id: String, + approved: bool, +) -> Result, ContractError> { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + + let querier = EvmQuerier::new(&deps.querier); + let mut payload_spender = spender.clone(); + let mut action = "approve"; + if !approved { + payload_spender = "".to_string(); + action = "revoke"; + } + let payload = querier.erc1155_approve_payload(payload_spender, token_id.clone())?; + let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; + let res = Response::new() + .add_attribute("action", action) + .add_attribute("token_id", token_id) + .add_attribute("sender", info.sender) + .add_attribute("spender", spender.clone()) + .add_message(msg); + + Ok(res) +} + +pub fn execute_approve_all( + deps: DepsMut, + info: MessageInfo, + to: String, + approved: bool, +) -> Result, ContractError> { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + + let querier = EvmQuerier::new(&deps.querier); + let payload = querier.erc1155_set_approval_all_payload(to.clone(), approved)?; + let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; + let mut action = "approve_all"; + if !approved { + action = "revoke_all"; + } + let res = Response::new() + .add_attribute("action", action) + .add_attribute("operator", to) + .add_attribute("sender", info.sender) + .add_attribute("approved", format!("{}", approved)) + .add_message(msg); + + Ok(res) +} + +pub fn execute_burn() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn execute_burn_batch() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn execute_mint() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn execute_mint_batch() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn update_ownership() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn execute_extension() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { + match msg { + QueryMsg::BalanceOf { owner, token_id } => to_json_binary(&query_balance_of(deps, env, owner, token_id)?), + QueryMsg::BalanceOfBatch { .. } => { + todo!() + }, + QueryMsg::TokenApprovals { .. } => { + todo!() + }, + QueryMsg::AllBalances { .. } => { + todo!() + }, + QueryMsg::IsApprovedForAll { owner, operator } => to_json_binary(&query_is_approved_for_all(deps, env, owner, operator)?), + QueryMsg::ApprovalsForAll { + owner, + include_expired: _, + start_after, + limit, + } => to_json_binary(&query_all_operators( + deps, + env, + owner, + start_after, + limit, + )?), + QueryMsg::NumTokens { token_id } => { + todo!() + }, + QueryMsg::Tokens { + owner, + start_after, + limit, + } => to_json_binary(&query_tokens( + deps, + env, + owner, + start_after, + limit, + )?), + QueryMsg::AllTokens { start_after, limit } => to_json_binary(&query_all_tokens( + deps, + env, + start_after, + limit, + )?), + QueryMsg::Minter {} => to_json_binary(&query_minter()?), + QueryMsg::Ownership {} => to_json_binary(&query_ownership()?), + QueryMsg::ContractInfo {} => to_json_binary(&query_contract_info(deps, env)?), + QueryMsg::TokenInfo { token_id } => to_json_binary(&query_nft_info(deps, env, token_id)?), + QueryMsg::AllTokenInfo { start_after, limit } => { + todo!() + // to_json_binary(&query_all_nft_info(deps, env, token_id)?) + }, + QueryMsg::Extension { msg } => match msg { + CwErc1155QueryMsg::EvmAddress {} => { + to_json_binary(&ERC1155_ADDRESS.load(deps.storage)?) + } + CwErc1155QueryMsg::RoyaltyInfo { + token_id, + sale_price, + } => to_json_binary(&query_royalty_info(deps, env, token_id, sale_price)?), + CwErc1155QueryMsg::CheckRoyalties {} => to_json_binary(&query_check_royalties(deps, env)?), + }, + }.map_err(Into::into) +} + +pub fn query_balance_of(deps: Deps, env: Env, owner: String, token_id: String) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let balance = Uint128::from_str(&querier.erc1155_balance_of(env.clone().contract.address.into_string(), erc_addr.clone(), owner, token_id.clone())?.amount)?; + Ok(BalanceResponse{ balance }) +} +pub fn query_is_approved_for_all(deps: Deps, env: Env, owner: String, operator: String) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let is_approved = querier.erc1155_is_approved_for_all(env.clone().contract.address.into_string(), erc_addr.clone(), owner.clone(), operator.clone())?.is_approved; + if is_approved { + return Ok(OperatorResponse{approval: Approval{spender: operator.clone(), expires: cw721::Expiration::Never {}}}); + } + Err(StdError::not_found("approval")) +} + +pub fn query_contract_info(deps: Deps, env: Env) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let res = querier.erc1155_name_symbol(env.clone().contract.address.into_string(), erc_addr.clone())?; + Ok(ContractInfoResponse{name: res.name, symbol: res.symbol}) +} + +pub fn query_nft_info( + deps: Deps, + env: Env, + token_id: String, +) -> StdResult> { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let res = querier.erc1155_uri( + env.clone().contract.address.into_string(), + erc_addr.clone(), + token_id.clone(), + )?; + let royalty_info = query_royalty_info(deps, env, token_id, 100u128.into()); + Ok(NftInfoResponse { + token_uri: Some(res.uri), + extension: Some(Cw2981Metadata { + image: None, + image_data: None, + external_url: None, + description: None, + name: None, + attributes: None, + background_color: None, + animation_url: None, + youtube_url: None, + royalty_percentage: if let Ok(royalty_info) = &royalty_info { + Some(royalty_info.royalty_amount.u128() as u64) + } else { + None + }, + royalty_payment_address: if let Ok(royalty_info) = royalty_info { + Some(royalty_info.address) + } else { + None + }, + }), + }) +} + +pub fn query_all_nft_info( + deps: Deps, + env: Env, + token_id: String, +) -> StdResult> { + todo!() + // let owner_of_res = query_balance_of(deps, env.clone(), token_id.to_string())?; + // let nft_info_res = query_nft_info(deps, env, token_id)?; + // Ok(AllNftInfoResponse { + // access: owner_of_res, + // info: nft_info_res, + // }) +} + +pub fn query_tokens( + deps: Deps, + env: Env, + owner: String, + start_after: Option, + limit: Option, +) -> StdResult { + todo!() + // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + // let querier = EvmQuerier::new(&deps.querier); + // let num_tokens = query_num_tokens(deps, env.clone())?.count; + // let start_after_id = Int256::from_str(&start_after.unwrap_or("-1".to_string()))?; + // let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; + // + // let mut cur = Int256::zero(); + // let mut counter = 0; + // let mut tokens: Vec = vec![]; + // while counter < num_tokens && tokens.len() < limit { + // let cur_str = cur.to_string(); + // let t_owner = match querier.erc1155_balance_of( + // env.clone().contract.address.into_string(), + // erc_addr.clone(), + // cur_str.to_string(), + // ) { + // Ok(res) => res.amount, + // Err(_) => "".to_string(), + // }; + // if t_owner != "" { + // counter += 1; + // if (owner.is_empty() || t_owner == owner) && cur > start_after_id { + // tokens.push(cur_str); + // } + // } + // cur += Int256::one(); + // } + // Ok(TokensResponse { tokens }) +} + +pub fn query_all_tokens( + deps: Deps, + env: Env, + start_after: Option, + limit: Option, +) -> StdResult { + query_tokens(deps, env, "".to_string(), start_after, limit) +} + +pub fn query_royalty_info( + deps: Deps, + env: Env, + token_id: String, + sale_price: Uint128, +) -> StdResult { + todo!() + // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + // let querier = EvmQuerier::new(&deps.querier); + // let res = querier.erc1155_royalty_info( + // env.clone().contract.address.into_string(), + // erc_addr.clone(), + // token_id, + // sale_price, + // )?; + // Ok(RoyaltiesInfoResponse { + // address: res.receiver, + // royalty_amount: res.royalty_amount, + // }) +} + +pub fn query_check_royalties(deps: Deps, env: Env,) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let res = querier.supports_interface(env.clone().contract.address.into_string(),erc_addr.clone(), ERC2981_ID.to_string())?; + Ok(CheckRoyaltiesResponse { + royalty_payments: res.supported, + }) +} + +pub fn query_minter() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn query_ownership() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn query_all_operators( + _deps: Deps, + _env: Env, + _owner: String, + _start_after: Option, + _limit: Option, +) -> Result { + Err(ContractError::NotSupported {}) +} + +pub fn query_num_tokens(deps: Deps, env: Env) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let res = querier + .erc1155_total_supply(env.clone().contract.address.into_string(), erc_addr.clone())?; + Ok(NumTokensResponse { + count: res.supply.u128() as u64, + }) +} diff --git a/example/cosmwasm/cw1155/src/error.rs b/example/cosmwasm/cw1155/src/error.rs new file mode 100644 index 000000000..32c333b07 --- /dev/null +++ b/example/cosmwasm/cw1155/src/error.rs @@ -0,0 +1,11 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("ERC1155 does not have the requested functionality in specification")] + NotSupported {}, +} diff --git a/example/cosmwasm/cw1155/src/lib.rs b/example/cosmwasm/cw1155/src/lib.rs new file mode 100644 index 000000000..454b5bc86 --- /dev/null +++ b/example/cosmwasm/cw1155/src/lib.rs @@ -0,0 +1,5 @@ +pub mod contract; +pub mod error; +pub mod msg; +pub mod querier; +pub mod state; diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs new file mode 100644 index 000000000..7fb318003 --- /dev/null +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -0,0 +1,200 @@ +use cosmwasm_std::{CosmosMsg, CustomMsg, CustomQuery, Uint128}; +use schemars::JsonSchema; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cw1155::Cw1155QueryMsg; +use serde::{Deserialize, Serialize}; + +#[cw_serde] +pub struct InstantiateMsg { + pub erc1155_address: String, +} + +pub type QueryMsg = Cw1155QueryMsg; + +/// SeiRoute is enum type to represent sei query route path +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum Route { + Evm, +} + +/// EvmQueryWrapper is an override of QueryRequest::Custom to access EVM +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct EvmQueryWrapper { + pub route: Route, + pub query_data: EvmQuery, +} + +// implement custom query +impl CustomQuery for EvmQueryWrapper {} + +/// EvmQuery is defines available query datas +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum EvmQuery { + Erc1155TransferSinglePayload { + from: String, + recipient: String, + token_id: String, + amount: Uint128, + }, + Erc1155TransferBatchPayload { + from: String, + recipient: String, + token_ids: Vec, + amounts: Vec, + }, + Erc1155ApprovePayload { + spender: String, + token_id: String, + }, + Erc1155BalanceOf { + caller: String, + contract_address: String, + owner: String, + token_id: String, + }, + Erc1155Approved { + caller: String, + contract_address: String, + token_id: String, + }, + Erc1155IsApprovedForAll { + caller: String, + contract_address: String, + owner: String, + operator: String, + }, + Erc1155SetApprovalAllPayload { + to: String, + approved: bool, + }, + Erc1155NameSymbol { + caller: String, + contract_address: String, + }, + Erc1155Uri { + caller: String, + contract_address: String, + token_id: String, + }, + Erc1155RoyaltyInfo { + caller: String, + contract_address: String, + token_id: String, + sale_price: Uint128, + }, + SupportsInterface { + caller: String, + contract_address: String, + interface_id: String, + }, + Erc1155TotalSupply { + caller: String, + contract_address: String, + }, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ErcPayloadResponse { + pub encoded_payload: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155BalanceOfResponse { + pub amount: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155ApprovedResponse { + pub approved: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155IsApprovedForAllResponse { + pub is_approved: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155NameSymbolResponse { + pub name: String, + pub symbol: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155UriResponse { + pub uri: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155RoyaltyInfoResponse { + pub receiver: String, + pub royalty_amount: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct SupportsInterfaceResponse { + pub supported: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155TotalSupplyResponse { + pub supply: Uint128, +} + +// implement custom query +impl CustomMsg for EvmMsg {} + +// this is a helper to be able to return these as CosmosMsg easier +impl From for CosmosMsg { + fn from(original: EvmMsg) -> Self { + CosmosMsg::Custom(original) + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum EvmMsg { + DelegateCallEvm { + to: String, + data: String, // base64 encoded + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum CwErc1155QueryMsg { + #[returns(String)] + EvmAddress {}, + + // cw2981 + /// Should be called on sale to see if royalties are owed + /// by the marketplace selling the NFT, if CheckRoyalties + /// returns true + /// See https://eips.ethereum.org/EIPS/eip-2981 + #[returns(cw2981_royalties::msg::RoyaltiesInfoResponse)] + RoyaltyInfo { + token_id: String, + // the denom of this sale must also be the denom returned by RoyaltiesInfoResponse + // this was originally implemented as a Coin + // however that would mean you couldn't buy using CW20s + // as CW20 is just mapping of addr -> balance + sale_price: Uint128, + }, + /// Called against contract to determine if this NFT + /// implements royalties. Should return a boolean as part of + /// CheckRoyaltiesResponse - default can simply be true + /// if royalties are implemented at token level + /// (i.e. always check on sale) + #[returns(cw2981_royalties::msg::CheckRoyaltiesResponse)] + CheckRoyalties {}, +} + +impl Default for CwErc1155QueryMsg { + fn default() -> Self { + CwErc1155QueryMsg::EvmAddress {} + } +} + +impl CustomMsg for CwErc1155QueryMsg {} \ No newline at end of file diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs new file mode 100644 index 000000000..842f7c6a9 --- /dev/null +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -0,0 +1,177 @@ +use cosmwasm_std::{QuerierWrapper, StdResult, Uint128}; + +use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155ApprovedResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse}; + +pub const DEFAULT_LIMIT: u32 = 10; +pub const MAX_LIMIT: u32 = 30; + +pub struct EvmQuerier<'a> { + querier: &'a QuerierWrapper<'a, EvmQueryWrapper>, +} + +impl<'a> EvmQuerier<'a> { + pub fn new(querier: &'a QuerierWrapper) -> Self { + EvmQuerier { querier } + } + + pub fn erc1155_balance_of(&self, caller: String, contract_address: String, owner: String, token_id: String) -> StdResult { + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155BalanceOf { caller, contract_address, owner, token_id }, + } + .into(); + + self.querier.query(&request) + } + + pub fn erc1155_approved(&self, caller: String, contract_address: String, token_id: String) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155Approved { caller, contract_address, token_id }, + // } + // .into(); + // + // self.querier.query(&request) + } + + pub fn erc1155_is_approved_for_all(&self, caller: String, contract_address: String, owner: String, operator: String) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155IsApprovedForAll { caller, contract_address, owner, operator }, + // } + // .into(); + // + // self.querier.query(&request) + } + + pub fn erc1155_name_symbol(&self, caller: String, contract_address: String) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155NameSymbol { caller, contract_address }, + // } + // .into(); + // + // self.querier.query(&request) + } + + pub fn erc1155_uri(&self, caller: String, contract_address: String, token_id: String,) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155Uri { caller, contract_address, token_id }, + // } + // .into(); + // + // self.querier.query(&request) + } + + // returns base64-encoded bytes + pub fn erc1155_transfer_single_payload(&self, from: String, recipient: String, token_id: String, amount: Uint128) -> StdResult { + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155TransferSinglePayload { + from, recipient, token_id, amount + }, + } + .into(); + + self.querier.query(&request) + } + + // returns base64-encoded bytes + pub fn erc1155_transfer_batch_payload(&self, from: String, recipient: String, token_ids: Vec, amounts: Vec) -> StdResult { + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155TransferBatchPayload { + from, recipient, token_ids, amounts + }, + } + .into(); + + self.querier.query(&request) + } + + // returns base64-encoded bytes + pub fn erc1155_approve_payload(&self, spender: String, token_id: String) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155ApprovePayload { + // spender, token_id, + // }, + // } + // .into(); + // + // self.querier.query(&request) + } + + // returns base64-encoded bytes + pub fn erc1155_set_approval_all_payload(&self, to: String, approved: bool) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155SetApprovalAllPayload { to, approved, }, + // } + // .into(); + // + // self.querier.query(&request) + } + + pub fn erc1155_royalty_info( + &self, + caller: String, + contract_address: String, + token_id: String, + sale_price: Uint128, + ) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155RoyaltyInfo { + // caller, + // contract_address, + // token_id, + // sale_price, + // }, + // } + // .into(); + // + // self.querier.query(&request) + } + + pub fn supports_interface( + &self, + caller: String, + contract_address: String, + interface_id: String, + ) -> StdResult { + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::SupportsInterface { caller, interface_id, contract_address, }, + } + .into(); + + self.querier.query(&request) + } + + pub fn erc1155_total_supply( + &self, + caller: String, + contract_address: String, + ) -> StdResult { + todo!() + // let request = EvmQueryWrapper { + // route: Route::Evm, + // query_data: EvmQuery::Erc1155TotalSupply { + // caller, + // contract_address, + // }, + // } + // .into(); + // + // self.querier.query(&request) + } +} \ No newline at end of file diff --git a/example/cosmwasm/cw1155/src/state.rs b/example/cosmwasm/cw1155/src/state.rs new file mode 100644 index 000000000..af2d0b131 --- /dev/null +++ b/example/cosmwasm/cw1155/src/state.rs @@ -0,0 +1,3 @@ +use cw_storage_plus::Item; + +pub const ERC1155_ADDRESS: Item = Item::new("erc1155_address"); \ No newline at end of file From 33d8bfdfc92c5d72daafec3454ae020a42dbad49 Mon Sep 17 00:00:00 2001 From: shab Date: Wed, 5 Jun 2024 14:02:02 -0400 Subject: [PATCH 02/65] cleanup todos --- example/cosmwasm/cw1155/src/contract.rs | 53 +++++++---- example/cosmwasm/cw1155/src/msg.rs | 9 ++ example/cosmwasm/cw1155/src/querier.rs | 120 +++++++++++++----------- 3 files changed, 106 insertions(+), 76 deletions(-) diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index 20a1af1ae..3f1fb1ab9 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -226,13 +226,15 @@ pub fn execute_extension() -> Result, ContractError> { pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { match msg { QueryMsg::BalanceOf { owner, token_id } => to_json_binary(&query_balance_of(deps, env, owner, token_id)?), - QueryMsg::BalanceOfBatch { .. } => { - todo!() + QueryMsg::BalanceOfBatch { owner, token_ids } => { + to_json_binary(&query_balance_of_batch(deps, env, owner, token_ids)?) }, QueryMsg::TokenApprovals { .. } => { + // todo - is this implemented in erc1155? todo!() }, QueryMsg::AllBalances { .. } => { + // todo - is this implemented in erc1155? todo!() }, QueryMsg::IsApprovedForAll { owner, operator } => to_json_binary(&query_is_approved_for_all(deps, env, owner, operator)?), @@ -249,7 +251,12 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { - todo!() + if let Some(token_id) = token_id { + // todo - is this implemented in erc1155? + return Err(ContractError::NotSupported {}) + } else { + to_json_binary(&query_num_tokens(deps, env)?) + } }, QueryMsg::Tokens { owner, @@ -273,8 +280,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result to_json_binary(&query_contract_info(deps, env)?), QueryMsg::TokenInfo { token_id } => to_json_binary(&query_nft_info(deps, env, token_id)?), QueryMsg::AllTokenInfo { start_after, limit } => { - todo!() - // to_json_binary(&query_all_nft_info(deps, env, token_id)?) + to_json_binary(&query_all_nft_info(deps, env)?) }, QueryMsg::Extension { msg } => match msg { CwErc1155QueryMsg::EvmAddress {} => { @@ -295,6 +301,14 @@ pub fn query_balance_of(deps: Deps, env: Env, owner: String, to let balance = Uint128::from_str(&querier.erc1155_balance_of(env.clone().contract.address.into_string(), erc_addr.clone(), owner, token_id.clone())?.amount)?; Ok(BalanceResponse{ balance }) } + +pub fn query_balance_of_batch(deps: Deps, env: Env, owner: String, token_ids: Vec) -> StdResult { + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let balance = Uint128::from_str(&querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, owner, token_ids)?.amount)?; + Ok(BalanceResponse{ balance }) +} + pub fn query_is_approved_for_all(deps: Deps, env: Env, owner: String, operator: String) -> StdResult { let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; let querier = EvmQuerier::new(&deps.querier); @@ -354,8 +368,9 @@ pub fn query_nft_info( pub fn query_all_nft_info( deps: Deps, env: Env, - token_id: String, + // token_id: String, ) -> StdResult> { + // todo - is this implemented in erc1155? todo!() // let owner_of_res = query_balance_of(deps, env.clone(), token_id.to_string())?; // let nft_info_res = query_nft_info(deps, env, token_id)?; @@ -372,6 +387,7 @@ pub fn query_tokens( start_after: Option, limit: Option, ) -> StdResult { + // todo - is this implemented in erc1155? todo!() // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; // let querier = EvmQuerier::new(&deps.querier); @@ -418,19 +434,18 @@ pub fn query_royalty_info( token_id: String, sale_price: Uint128, ) -> StdResult { - todo!() - // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; - // let querier = EvmQuerier::new(&deps.querier); - // let res = querier.erc1155_royalty_info( - // env.clone().contract.address.into_string(), - // erc_addr.clone(), - // token_id, - // sale_price, - // )?; - // Ok(RoyaltiesInfoResponse { - // address: res.receiver, - // royalty_amount: res.royalty_amount, - // }) + let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + let querier = EvmQuerier::new(&deps.querier); + let res = querier.erc1155_royalty_info( + env.clone().contract.address.into_string(), + erc_addr.clone(), + token_id, + sale_price, + )?; + Ok(RoyaltiesInfoResponse { + address: res.receiver, + royalty_amount: res.royalty_amount, + }) } pub fn query_check_royalties(deps: Deps, env: Env,) -> StdResult { diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs index 7fb318003..0b8b31de9 100644 --- a/example/cosmwasm/cw1155/src/msg.rs +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -45,6 +45,7 @@ pub enum EvmQuery { token_ids: Vec, amounts: Vec, }, + // todo - is this implemented in erc1155? Erc1155ApprovePayload { spender: String, token_id: String, @@ -55,6 +56,13 @@ pub enum EvmQuery { owner: String, token_id: String, }, + Erc1155BalanceOfBatch { + caller: String, + contract_address: String, + owner: String, + token_ids: Vec, + }, + // todo - is this implemented in erc1155? Erc1155Approved { caller: String, contract_address: String, @@ -79,6 +87,7 @@ pub enum EvmQuery { contract_address: String, token_id: String, }, + // todo - quantity field? Erc1155RoyaltyInfo { caller: String, contract_address: String, diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs index 842f7c6a9..eb10412d4 100644 --- a/example/cosmwasm/cw1155/src/querier.rs +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -19,12 +19,23 @@ impl<'a> EvmQuerier<'a> { route: Route::Evm, query_data: EvmQuery::Erc1155BalanceOf { caller, contract_address, owner, token_id }, } - .into(); + .into(); + + self.querier.query(&request) + } + + pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, owner: String, token_ids: Vec) -> StdResult { + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155BalanceOfBatch { caller, contract_address, owner, token_ids }, + } + .into(); self.querier.query(&request) } pub fn erc1155_approved(&self, caller: String, contract_address: String, token_id: String) -> StdResult { + // todo - is this implemented in erc1155? todo!() // let request = EvmQueryWrapper { // route: Route::Evm, @@ -36,36 +47,33 @@ impl<'a> EvmQuerier<'a> { } pub fn erc1155_is_approved_for_all(&self, caller: String, contract_address: String, owner: String, operator: String) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155IsApprovedForAll { caller, contract_address, owner, operator }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155IsApprovedForAll { caller, contract_address, owner, operator }, + } + .into(); + + self.querier.query(&request) } pub fn erc1155_name_symbol(&self, caller: String, contract_address: String) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155NameSymbol { caller, contract_address }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155NameSymbol { caller, contract_address }, + } + .into(); + + self.querier.query(&request) } pub fn erc1155_uri(&self, caller: String, contract_address: String, token_id: String,) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155Uri { caller, contract_address, token_id }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155Uri { caller, contract_address, token_id }, + } + .into(); + + self.querier.query(&request) } // returns base64-encoded bytes @@ -96,6 +104,7 @@ impl<'a> EvmQuerier<'a> { // returns base64-encoded bytes pub fn erc1155_approve_payload(&self, spender: String, token_id: String) -> StdResult { + // todo - is this implemented in erc1155? todo!() // let request = EvmQueryWrapper { // route: Route::Evm, @@ -110,14 +119,13 @@ impl<'a> EvmQuerier<'a> { // returns base64-encoded bytes pub fn erc1155_set_approval_all_payload(&self, to: String, approved: bool) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155SetApprovalAllPayload { to, approved, }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155SetApprovalAllPayload { to, approved, }, + } + .into(); + + self.querier.query(&request) } pub fn erc1155_royalty_info( @@ -127,19 +135,18 @@ impl<'a> EvmQuerier<'a> { token_id: String, sale_price: Uint128, ) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155RoyaltyInfo { - // caller, - // contract_address, - // token_id, - // sale_price, - // }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155RoyaltyInfo { + caller, + contract_address, + token_id, + sale_price, + }, + } + .into(); + + self.querier.query(&request) } pub fn supports_interface( @@ -162,16 +169,15 @@ impl<'a> EvmQuerier<'a> { caller: String, contract_address: String, ) -> StdResult { - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155TotalSupply { - // caller, - // contract_address, - // }, - // } - // .into(); - // - // self.querier.query(&request) + let request = EvmQueryWrapper { + route: Route::Evm, + query_data: EvmQuery::Erc1155TotalSupply { + caller, + contract_address, + }, + } + .into(); + + self.querier.query(&request) } } \ No newline at end of file From 006148323db05ec6db8f8b78718dffc89c6f43b0 Mon Sep 17 00:00:00 2001 From: shab Date: Wed, 5 Jun 2024 14:52:23 -0400 Subject: [PATCH 03/65] sync events with current standard --- example/cosmwasm/cw1155/src/contract.rs | 90 +++++++++++-------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index 3f1fb1ab9..35f333b0d 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -1,15 +1,15 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{DepsMut, Deps, Env, MessageInfo, Response, Binary, StdResult, to_json_binary, Empty, Uint128, Int256, StdError}; -use cw721::{Cw721ReceiveMsg, OwnerOfResponse, Approval, ApprovalResponse, ApprovalsResponse, OperatorResponse, ContractInfoResponse, NftInfoResponse, AllNftInfoResponse, TokensResponse, OperatorsResponse, NumTokensResponse}; +use cosmwasm_std::{DepsMut, Deps, Env, MessageInfo, Response, Binary, StdResult, to_json_binary, Uint128, StdError}; +use cw721::{Approval, OperatorResponse, ContractInfoResponse, NftInfoResponse, AllNftInfoResponse, TokensResponse, OperatorsResponse, NumTokensResponse}; use cw2981_royalties::msg::{RoyaltiesInfoResponse, CheckRoyaltiesResponse}; use cw2981_royalties::{Metadata as Cw2981Metadata, Extension as Cw2981Extension}; use crate::msg::{EvmQueryWrapper, EvmMsg, InstantiateMsg, CwErc1155QueryMsg, QueryMsg}; -use crate::querier::{EvmQuerier, DEFAULT_LIMIT, MAX_LIMIT}; +use crate::querier::{EvmQuerier}; use crate::error::ContractError; use crate::state::ERC1155_ADDRESS; use std::str::FromStr; -use cw1155::{BalanceResponse, Cw1155BatchReceiveMsg, Cw1155QueryMsg, Cw1155ReceiveMsg, TokenAmount}; +use cw1155::{ApproveAllEvent, BalanceResponse, Cw1155BatchReceiveMsg, Cw1155ReceiveMsg, RevokeAllEvent, TokenAmount, TransferEvent}; use cw1155_royalties::Cw1155RoyaltiesExecuteMsg; const ERC2981_ID: &str = "0x2a55205a"; @@ -88,17 +88,10 @@ pub fn execute_send_single( amount, msg, }; - res = res - .add_message(send.into_cosmos_msg(recipient.to_string())?) - .add_attribute("action", "send_single"); - } else { - res = res.add_attribute("action", "transfer_single") + res = res.add_message(send.into_cosmos_msg(recipient.to_string())?) } - res = res.add_attribute("sender", info.sender) - .add_attribute("recipient", recipient) - .add_attribute("token_id", token_id) - .add_attribute("amount", amount); + res = res.add_event(TransferEvent::new(&info.sender, &recipient, vec![TokenAmount{ token_id, amount }]).into()); Ok(res) } @@ -128,20 +121,13 @@ pub fn execute_send_batch( let send = Cw1155BatchReceiveMsg { operator: info.sender.to_string(), from, - batch, + batch: batch.to_vec(), msg, }; - res = res - .add_message(send.into_cosmos_msg(recipient.to_string())?) - .add_attribute("action", "send_batch"); - } else { - res = res.add_attribute("action", "transfer_batch") + res = res.add_message(send.into_cosmos_msg(recipient.to_string())?); } - res = res.add_attribute("sender", info.sender) - .add_attribute("recipient", recipient) - .add_attribute("token_ids", token_ids.join(",")) - .add_attribute("amounts", amounts.iter().map(|a| a.to_string()).collect::>().join(",")); + res = res.add_event(TransferEvent::new(&info.sender, &recipient, batch).into()); Ok(res) } @@ -152,25 +138,27 @@ pub fn execute_approve( token_id: String, approved: bool, ) -> Result, ContractError> { - let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; - - let querier = EvmQuerier::new(&deps.querier); - let mut payload_spender = spender.clone(); - let mut action = "approve"; - if !approved { - payload_spender = "".to_string(); - action = "revoke"; - } - let payload = querier.erc1155_approve_payload(payload_spender, token_id.clone())?; - let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; - let res = Response::new() - .add_attribute("action", action) - .add_attribute("token_id", token_id) - .add_attribute("sender", info.sender) - .add_attribute("spender", spender.clone()) - .add_message(msg); - - Ok(res) + // todo - is this implemented in erc1155? + todo!() + // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; + // + // let querier = EvmQuerier::new(&deps.querier); + // let mut payload_spender = spender.clone(); + // let mut action = "approve"; + // if !approved { + // payload_spender = "".to_string(); + // action = "revoke"; + // } + // let payload = querier.erc1155_approve_payload(payload_spender, token_id.clone())?; + // let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; + // let res = Response::new() + // .add_attribute("action", action) + // .add_attribute("token_id", token_id) + // .add_attribute("sender", info.sender) + // .add_attribute("spender", spender.clone()) + // .add_message(msg); + // + // Ok(res) } pub fn execute_approve_all( @@ -183,17 +171,17 @@ pub fn execute_approve_all( let querier = EvmQuerier::new(&deps.querier); let payload = querier.erc1155_set_approval_all_payload(to.clone(), approved)?; + let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; - let mut action = "approve_all"; - if !approved { - action = "revoke_all"; - } + let event = if approved { + ApproveAllEvent::new(&info.sender, &deps.api.addr_validate(&to)?).into() + } else { + RevokeAllEvent::new(&info.sender, &deps.api.addr_validate(&to)?).into() + }; + let res = Response::new() - .add_attribute("action", action) - .add_attribute("operator", to) - .add_attribute("sender", info.sender) - .add_attribute("approved", format!("{}", approved)) - .add_message(msg); + .add_message(msg) + .add_event(event); Ok(res) } From 9f0d2990a181ea51c02ddbb50b3fabf2573a5b73 Mon Sep 17 00:00:00 2001 From: shab Date: Wed, 5 Jun 2024 15:33:57 -0400 Subject: [PATCH 04/65] fix query BalanceOfBatch --- example/cosmwasm/cw1155/Cargo.lock | 26 ++++++++++++------------- example/cosmwasm/cw1155/Cargo.toml | 4 ++-- example/cosmwasm/cw1155/src/contract.rs | 12 ++++++------ example/cosmwasm/cw1155/src/msg.rs | 4 ++-- example/cosmwasm/cw1155/src/querier.rs | 14 +++++++++---- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/example/cosmwasm/cw1155/Cargo.lock b/example/cosmwasm/cw1155/Cargo.lock index 19f2d7833..7623620ec 100644 --- a/example/cosmwasm/cw1155/Cargo.lock +++ b/example/cosmwasm/cw1155/Cargo.lock @@ -282,14 +282,14 @@ dependencies = [ [[package]] name = "cw1155" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-ownable", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -298,7 +298,7 @@ dependencies = [ [[package]] name = "cw1155-base" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -307,8 +307,8 @@ dependencies = [ "cw-utils 1.0.3", "cw1155", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", - "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", "schemars", "serde", ] @@ -316,13 +316,13 @@ dependencies = [ [[package]] name = "cw1155-royalties" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-std", "cw1155", "cw1155-base", "cw2 1.1.2", - "cw2981-royalties 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw2981-royalties 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -375,13 +375,13 @@ dependencies = [ [[package]] name = "cw2981-royalties" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", - "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -416,7 +416,7 @@ dependencies = [ [[package]] name = "cw721" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -464,7 +464,7 @@ dependencies = [ [[package]] name = "cw721-base" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08#cfa0c084023c3cef6d9be4ae510a6ae77c963aaf" +source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -472,7 +472,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=cfa0c08)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", "cw721-base 0.16.0", "schemars", "serde", diff --git a/example/cosmwasm/cw1155/Cargo.toml b/example/cosmwasm/cw1155/Cargo.toml index d172eb9c2..a266d5687 100644 --- a/example/cosmwasm/cw1155/Cargo.toml +++ b/example/cosmwasm/cw1155/Cargo.toml @@ -17,8 +17,8 @@ library = [] cosmwasm-schema = "1.5.0" cosmwasm-std = { version = "1.3.1", features = ["staking", "stargate"] } cw-storage-plus = "1.2.0" -cw1155-royalties = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "cfa0c08" } -cw1155 = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "cfa0c08" } +cw1155-royalties = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "3751bf6" } +cw1155 = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "3751bf6" } cw2981-royalties = "0.18.0" cw721 = "0.18.0" cw721-base = "0.18.0" diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index 35f333b0d..5f5037a25 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -9,7 +9,7 @@ use crate::querier::{EvmQuerier}; use crate::error::ContractError; use crate::state::ERC1155_ADDRESS; use std::str::FromStr; -use cw1155::{ApproveAllEvent, BalanceResponse, Cw1155BatchReceiveMsg, Cw1155ReceiveMsg, RevokeAllEvent, TokenAmount, TransferEvent}; +use cw1155::{ApproveAllEvent, BalanceResponse, Cw1155BatchReceiveMsg, Cw1155ReceiveMsg, OwnerToken, RevokeAllEvent, TokenAmount, TransferEvent}; use cw1155_royalties::Cw1155RoyaltiesExecuteMsg; const ERC2981_ID: &str = "0x2a55205a"; @@ -213,9 +213,9 @@ pub fn execute_extension() -> Result, ContractError> { #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { match msg { - QueryMsg::BalanceOf { owner, token_id } => to_json_binary(&query_balance_of(deps, env, owner, token_id)?), - QueryMsg::BalanceOfBatch { owner, token_ids } => { - to_json_binary(&query_balance_of_batch(deps, env, owner, token_ids)?) + QueryMsg::BalanceOf(OwnerToken { owner, token_id }) => to_json_binary(&query_balance_of(deps, env, owner, token_id)?), + QueryMsg::BalanceOfBatch(batch) => { + to_json_binary(&query_balance_of_batch(deps, env, batch)?) }, QueryMsg::TokenApprovals { .. } => { // todo - is this implemented in erc1155? @@ -290,10 +290,10 @@ pub fn query_balance_of(deps: Deps, env: Env, owner: String, to Ok(BalanceResponse{ balance }) } -pub fn query_balance_of_batch(deps: Deps, env: Env, owner: String, token_ids: Vec) -> StdResult { +pub fn query_balance_of_batch(deps: Deps, env: Env, batch: Vec) -> StdResult { let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; let querier = EvmQuerier::new(&deps.querier); - let balance = Uint128::from_str(&querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, owner, token_ids)?.amount)?; + let balance = Uint128::from_str(&querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, batch)?.amount)?; Ok(BalanceResponse{ balance }) } diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs index 0b8b31de9..bdad4be37 100644 --- a/example/cosmwasm/cw1155/src/msg.rs +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -53,13 +53,13 @@ pub enum EvmQuery { Erc1155BalanceOf { caller: String, contract_address: String, - owner: String, + account: String, token_id: String, }, Erc1155BalanceOfBatch { caller: String, contract_address: String, - owner: String, + accounts: Vec, token_ids: Vec, }, // todo - is this implemented in erc1155? diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs index eb10412d4..cdda08181 100644 --- a/example/cosmwasm/cw1155/src/querier.rs +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -1,4 +1,5 @@ use cosmwasm_std::{QuerierWrapper, StdResult, Uint128}; +use cw1155::OwnerToken; use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155ApprovedResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse}; @@ -14,20 +15,25 @@ impl<'a> EvmQuerier<'a> { EvmQuerier { querier } } - pub fn erc1155_balance_of(&self, caller: String, contract_address: String, owner: String, token_id: String) -> StdResult { + pub fn erc1155_balance_of(&self, caller: String, contract_address: String, account: String, token_id: String) -> StdResult { let request = EvmQueryWrapper { route: Route::Evm, - query_data: EvmQuery::Erc1155BalanceOf { caller, contract_address, owner, token_id }, + query_data: EvmQuery::Erc1155BalanceOf { caller, contract_address, account, token_id }, } .into(); self.querier.query(&request) } - pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, owner: String, token_ids: Vec) -> StdResult { + pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, batch: Vec) -> StdResult { let request = EvmQueryWrapper { route: Route::Evm, - query_data: EvmQuery::Erc1155BalanceOfBatch { caller, contract_address, owner, token_ids }, + query_data: EvmQuery::Erc1155BalanceOfBatch { + caller, + contract_address, + accounts: batch.iter().map(|ot| ot.owner.to_string()).collect(), + token_ids: batch.iter().map(|ot| ot.token_id.to_string()).collect() + }, } .into(); From 45c654f84886645d333b27cd7f77116005a566f3 Mon Sep 17 00:00:00 2001 From: shab Date: Wed, 5 Jun 2024 16:44:15 -0400 Subject: [PATCH 05/65] fix import --- example/cosmwasm/cw1155/Cargo.lock | 26 +++++++++++++------------- example/cosmwasm/cw1155/Cargo.toml | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/example/cosmwasm/cw1155/Cargo.lock b/example/cosmwasm/cw1155/Cargo.lock index 7623620ec..cef628e2b 100644 --- a/example/cosmwasm/cw1155/Cargo.lock +++ b/example/cosmwasm/cw1155/Cargo.lock @@ -282,14 +282,14 @@ dependencies = [ [[package]] name = "cw1155" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-ownable", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -298,7 +298,7 @@ dependencies = [ [[package]] name = "cw1155-base" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -307,8 +307,8 @@ dependencies = [ "cw-utils 1.0.3", "cw1155", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", - "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", "schemars", "serde", ] @@ -316,13 +316,13 @@ dependencies = [ [[package]] name = "cw1155-royalties" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-std", "cw1155", "cw1155-base", "cw2 1.1.2", - "cw2981-royalties 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw2981-royalties 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -375,13 +375,13 @@ dependencies = [ [[package]] name = "cw2981-royalties" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", - "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", + "cw721-base 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", "schemars", "serde", "thiserror", @@ -416,7 +416,7 @@ dependencies = [ [[package]] name = "cw721" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -464,7 +464,7 @@ dependencies = [ [[package]] name = "cw721-base" version = "0.18.0" -source = "git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" +source = "git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6#3751bf6b4059ed573f7a1c883ee41ce92c7e07e6" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -472,7 +472,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts_ALPAC-4.git?rev=3751bf6)", + "cw721 0.18.0 (git+https://github.com/palletexchange/cw-nfts.git?rev=3751bf6)", "cw721-base 0.16.0", "schemars", "serde", diff --git a/example/cosmwasm/cw1155/Cargo.toml b/example/cosmwasm/cw1155/Cargo.toml index a266d5687..55e3deee9 100644 --- a/example/cosmwasm/cw1155/Cargo.toml +++ b/example/cosmwasm/cw1155/Cargo.toml @@ -17,8 +17,8 @@ library = [] cosmwasm-schema = "1.5.0" cosmwasm-std = { version = "1.3.1", features = ["staking", "stargate"] } cw-storage-plus = "1.2.0" -cw1155-royalties = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "3751bf6" } -cw1155 = { git = "https://github.com/palletexchange/cw-nfts_ALPAC-4.git", rev = "3751bf6" } +cw1155-royalties = { git = "https://github.com/palletexchange/cw-nfts.git", rev = "3751bf6" } +cw1155 = { git = "https://github.com/palletexchange/cw-nfts.git", rev = "3751bf6" } cw2981-royalties = "0.18.0" cw721 = "0.18.0" cw721-base = "0.18.0" From 026962738452d8f9a2f4fdbf5b34ea076927cbfa Mon Sep 17 00:00:00 2001 From: davyli Date: Sat, 15 Jun 2024 16:04:14 -0400 Subject: [PATCH 06/65] Fix up cwerc1155 compiled files --- .../cosmwasm/cw1155/artifacts/checksums.txt | 2 +- .../artifacts/checksums_intermediate.txt | 1 - ...{cwerc1155-aarch64.wasm => cwerc1155.wasm} | Bin x/evm/artifacts/erc1155/artifacts.go | 22 ++++++++++++++++++ x/evm/artifacts/erc1155/cwerc1155.wasm | Bin 0 -> 291992 bytes 5 files changed, 23 insertions(+), 2 deletions(-) delete mode 100644 example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt rename example/cosmwasm/cw1155/artifacts/{cwerc1155-aarch64.wasm => cwerc1155.wasm} (100%) create mode 100644 x/evm/artifacts/erc1155/artifacts.go create mode 100644 x/evm/artifacts/erc1155/cwerc1155.wasm diff --git a/example/cosmwasm/cw1155/artifacts/checksums.txt b/example/cosmwasm/cw1155/artifacts/checksums.txt index ddaed5356..59a4bf80c 100644 --- a/example/cosmwasm/cw1155/artifacts/checksums.txt +++ b/example/cosmwasm/cw1155/artifacts/checksums.txt @@ -1 +1 @@ -3ec5c08215a37ebd3bb5905cda377243b0946cecdc440d91bb11447e823da21d cwerc1155-aarch64.wasm +3ec5c08215a37ebd3bb5905cda377243b0946cecdc440d91bb11447e823da21d cwerc1155.wasm diff --git a/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt b/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt deleted file mode 100644 index bb4b3c1c8..000000000 --- a/example/cosmwasm/cw1155/artifacts/checksums_intermediate.txt +++ /dev/null @@ -1 +0,0 @@ -64e02d4e121693160aa8b9f08594807a98d24d64be1b84015c564cc59d0b6652 ./target/wasm32-unknown-unknown/release/cwerc1155.wasm diff --git a/example/cosmwasm/cw1155/artifacts/cwerc1155-aarch64.wasm b/example/cosmwasm/cw1155/artifacts/cwerc1155.wasm similarity index 100% rename from example/cosmwasm/cw1155/artifacts/cwerc1155-aarch64.wasm rename to example/cosmwasm/cw1155/artifacts/cwerc1155.wasm diff --git a/x/evm/artifacts/erc1155/artifacts.go b/x/evm/artifacts/erc1155/artifacts.go new file mode 100644 index 000000000..daefb4010 --- /dev/null +++ b/x/evm/artifacts/erc1155/artifacts.go @@ -0,0 +1,22 @@ +package erc721 + +import "embed" + +const CurrentVersion uint16 = 1 + +//go:embed cwerc1155.wasm +var f embed.FS + +var cachedBin []byte + +func GetBin() []byte { + if cachedBin != nil { + return cachedBin + } + bz, err := f.ReadFile("cwerc1155.wasm") + if err != nil { + panic("failed to read ERC1155 wrapper contract wasm") + } + cachedBin = bz + return bz +} diff --git a/x/evm/artifacts/erc1155/cwerc1155.wasm b/x/evm/artifacts/erc1155/cwerc1155.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a905d5e616d419c5a8cc58396b969e0c0536b327 GIT binary patch literal 291992 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

L7&* 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ⓈgN@1^WSP;)LOB;F>qdk}IDvdpvkjTjtf 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 Date: Thu, 20 Jun 2024 13:02:11 -0400 Subject: [PATCH 07/65] Add 1155 requests into bindings --- x/evm/client/wasm/bindings/queries.go | 50 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/x/evm/client/wasm/bindings/queries.go b/x/evm/client/wasm/bindings/queries.go index 420f1a81a..0afc09f99 100644 --- a/x/evm/client/wasm/bindings/queries.go +++ b/x/evm/client/wasm/bindings/queries.go @@ -5,26 +5,36 @@ import ( ) type SeiEVMQuery struct { - StaticCall *StaticCallRequest `json:"static_call,omitempty"` - ERC20TransferPayload *ERC20TransferPayloadRequest `json:"erc20_transfer_payload,omitempty"` - ERC20TransferFromPayload *ERC20TransferFromPayloadRequest `json:"erc20_transfer_from_payload,omitempty"` - ERC20ApprovePayload *ERC20ApprovePayloadRequest `json:"erc20_approve_payload,omitempty"` - ERC20Allowance *ERC20AllowanceRequest `json:"erc20_allowance,omitempty"` - ERC20TokenInfo *ERC20TokenInfoRequest `json:"erc20_token_info,omitempty"` - ERC20Balance *ERC20BalanceRequest `json:"erc20_balance,omitempty"` - ERC721Owner *ERC721OwnerRequest `json:"erc721_owner,omitempty"` - ERC721TransferPayload *ERC721TransferPayloadRequest `json:"erc721_transfer_payload,omitempty"` - ERC721ApprovePayload *ERC721ApprovePayloadRequest `json:"erc721_approve_payload,omitempty"` - ERC721SetApprovalAllPayload *ERC721SetApprovalAllPayloadRequest `json:"erc721_set_approval_all_payload,omitempty"` - ERC721Approved *ERC721ApprovedRequest `json:"erc721_approved,omitempty"` - ERC721IsApprovedForAll *ERC721IsApprovedForAllRequest `json:"erc721_is_approved_for_all,omitempty"` - ERC721TotalSupply *ERC721TotalSupplyRequest `json:"erc721_total_supply,omitempty"` - ERC721NameSymbol *ERC721NameSymbolRequest `json:"erc721_name_symbol,omitempty"` - ERC721Uri *ERC721UriRequest `json:"erc721_uri,omitempty"` - ERC721RoyaltyInfo *ERC721RoyaltyInfoRequest `json:"erc721_royalty_info,omitempty"` - GetEvmAddress *GetEvmAddressRequest `json:"get_evm_address,omitempty"` - GetSeiAddress *GetSeiAddressRequest `json:"get_sei_address,omitempty"` - SupportsInterface *SupportsInterfaceRequest `json:"supports_interface,omitempty"` + StaticCall *StaticCallRequest `json:"static_call,omitempty"` + ERC20TransferPayload *ERC20TransferPayloadRequest `json:"erc20_transfer_payload,omitempty"` + ERC20TransferFromPayload *ERC20TransferFromPayloadRequest `json:"erc20_transfer_from_payload,omitempty"` + ERC20ApprovePayload *ERC20ApprovePayloadRequest `json:"erc20_approve_payload,omitempty"` + ERC20Allowance *ERC20AllowanceRequest `json:"erc20_allowance,omitempty"` + ERC20TokenInfo *ERC20TokenInfoRequest `json:"erc20_token_info,omitempty"` + ERC20Balance *ERC20BalanceRequest `json:"erc20_balance,omitempty"` + ERC721Owner *ERC721OwnerRequest `json:"erc721_owner,omitempty"` + ERC721TransferPayload *ERC721TransferPayloadRequest `json:"erc721_transfer_payload,omitempty"` + ERC721ApprovePayload *ERC721ApprovePayloadRequest `json:"erc721_approve_payload,omitempty"` + ERC721SetApprovalAllPayload *ERC721SetApprovalAllPayloadRequest `json:"erc721_set_approval_all_payload,omitempty"` + ERC721Approved *ERC721ApprovedRequest `json:"erc721_approved,omitempty"` + ERC721IsApprovedForAll *ERC721IsApprovedForAllRequest `json:"erc721_is_approved_for_all,omitempty"` + ERC721TotalSupply *ERC721TotalSupplyRequest `json:"erc721_total_supply,omitempty"` + ERC721NameSymbol *ERC721NameSymbolRequest `json:"erc721_name_symbol,omitempty"` + ERC721Uri *ERC721UriRequest `json:"erc721_uri,omitempty"` + ERC721RoyaltyInfo *ERC721RoyaltyInfoRequest `json:"erc721_royalty_info,omitempty"` + ERC1155Owner *ERC1155OwnerRequest `json:"erc1155_owner,omitempty"` + ERC1155SendBatchPayload *ERC1155TransferPayloadRequest `json:"erc1155_transfer_payload,omitempty"` + ERC1155ApprovePayload *ERC1155ApprovePayloadRequest `json:"erc1155_approve_payload,omitempty"` + ERC1155SetApprovalAllPayload *ERC1155SetApprovalAllPayloadRequest `json:"erc1155_set_approval_all_payload,omitempty"` + ERC1155Approved *ERC1155ApprovedRequest `json:"erc1155_approved,omitempty"` + ERC1155IsApprovedForAll *ERC1155IsApprovedForAllRequest `json:"erc1155_is_approved_for_all,omitempty"` + ERC1155TotalSupply *ERC1155TotalSupplyRequest `json:"erc1155_total_supply,omitempty"` + ERC1155NameSymbol *ERC1155NameSymbolRequest `json:"erc1155_name_symbol,omitempty"` + ERC1155Uri *ERC1155UriRequest `json:"erc1155_uri,omitempty"` + ERC1155RoyaltyInfo *ERC1155RoyaltyInfoRequest `json:"erc1155_royalty_info,omitempty"` + GetEvmAddress *GetEvmAddressRequest `json:"get_evm_address,omitempty"` + GetSeiAddress *GetSeiAddressRequest `json:"get_sei_address,omitempty"` + SupportsInterface *SupportsInterfaceRequest `json:"supports_interface,omitempty"` } type StaticCallRequest struct { From 533bca6af3d0d802fdd1fb3f89d567604e6b9ab1 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Thu, 20 Jun 2024 20:57:24 +0100 Subject: [PATCH 08/65] queries --- contracts/src/CW1155ERC1155Pointer.sol | 102 +++++++++ .../test/CW1155toERC1155PointerTest.t.sol | 204 ++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 contracts/src/CW1155ERC1155Pointer.sol create mode 100644 contracts/test/CW1155toERC1155PointerTest.t.sol diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol new file mode 100644 index 000000000..caa15ae3d --- /dev/null +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import "@openzeppelin/contracts/token/common/ERC2981.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IWasmd} from "./precompiles/IWasmd.sol"; +import {IJson} from "./precompiles/IJson.sol"; +import {IAddr} from "./precompiles/IAddr.sol"; + + +contract CW1155ERC1155Pointer is ERC1155, ERC2981 { + + address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; + address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; + address constant ADDR_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001004; + + string public Cw1155Address; + IWasmd public WasmdPrecompile; + IJson public JsonPrecompile; + IAddr public AddrPrecompile; + + error NotImplementedOnCosmwasmContract(string method); + error NotImplemented(string method); + + constructor(string memory Cw1155Address_, string memory uri_) ERC1155(uri_) { + WasmdPrecompile = IWasmd(WASMD_PRECOMPILE_ADDRESS); + JsonPrecompile = IJson(JSON_PRECOMPILE_ADDRESS); + AddrPrecompile = IAddr(ADDR_PRECOMPILE_ADDRESS); + Cw1155Address = Cw1155Address_; + } + + function supportsInterface(bytes4 interfaceId) public pure override(ERC2981, ERC1155) returns (bool) { + return + interfaceId == type(IERC2981).interfaceId || + interfaceId == type(IERC1155).interfaceId || + interfaceId == type(IERC1155MetadataURI).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + + // Queries + function balanceOf(address account, uint256 id) public view override returns (uint256) { + require(account != address(0), "ERC1155: cannot query balance of zero address"); + string memory req = _curlyBrace( + _keyValue("balance_of",(_curlyBrace( + _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))),",",_keyValue("token_id", _doubleQuotes(Strings.toString(id)))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return JsonPrecompile.extractAsUint256(response, "balance"); + } + + function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view override returns (uint256[] memory balances){ + if(accounts.length != ids.length){ + revert ERC1155InvalidArrayLength(ids.length, accounts.length); + } + balances = new uint256[](accounts.length); + for(uint256 i = 0; i < accounts.length; i++){ + balances[i] = balanceOf(accounts[i], ids[i]); + } + } + + function uri(uint256 id) public view override returns (string memory) { + string memory req = _curlyBrace( + _keyValue("token_info",(_curlyBrace( + _keyValue("token_id", _doubleQuotes(Strings.toString(id))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return string(JsonPrecompile.extractAsBytes(response, "token_uri")); + } + + function isApprovedForAll(address owner, address operator) public view override returns (bool) { + string memory req = _curlyBrace( + _keyValue("is_approved_for_all",(_curlyBrace( + _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))),",",_keyValue("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator)))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return JsonPrecompile.extractAsUint256(response, "approved") == 1; + } + + + function _keyValue(string memory key, string memory value) internal pure returns (string memory) { + return _join(_doubleQuotes(key), ":", value); + } + + function _curlyBrace(string memory s) internal pure returns (string memory) { + return string.concat("{", string.concat(s, "}")); + } + + function _doubleQuotes(string memory s) internal pure returns (string memory) { + return string.concat("\"", string.concat(s, "\"")); + } + + function _join(string memory a, string memory separator, string memory b) internal pure returns (string memory) { + return string.concat(a, string.concat(separator, b)); + } +} diff --git a/contracts/test/CW1155toERC1155PointerTest.t.sol b/contracts/test/CW1155toERC1155PointerTest.t.sol new file mode 100644 index 000000000..9f9a12bc5 --- /dev/null +++ b/contracts/test/CW1155toERC1155PointerTest.t.sol @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test, console2} from "forge-std/Test.sol"; +import {CW1155ERC1155Pointer} from "../src/CW1155ERC1155Pointer.sol"; +import {IWasmd} from "../src/precompiles/IWasmd.sol"; +import {IJson} from "../src/precompiles/IJson.sol"; +import {IAddr} from "../src/precompiles/IAddr.sol"; +import "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; + +address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; +address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; +address constant ADDR_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001004; + +address constant MockCallerEVMAddr = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; +address constant MockOperatorEVMAddr = 0xF39fD6e51Aad88F6f4CE6AB8827279CFffb92267; +address constant MockZeroAddress = 0x0000000000000000000000000000000000000000; + +string constant MockCallerSeiAddr = "sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw"; +string constant MockOperatorSeiAddr = "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"; +string constant MockCWContractAddress = "sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m"; + +contract MockWasmd is IWasmd { + + // Transactions + function instantiate( + uint64, + string memory, + bytes memory, + string memory, + bytes memory + ) external pure returns (string memory, bytes memory) { + return (MockCWContractAddress, bytes("")); + } + + function execute( + string memory contractAddress, + bytes memory, + bytes memory + ) external pure returns (bytes memory) { + require(keccak256(abi.encodePacked(contractAddress)) == keccak256(abi.encodePacked(MockCWContractAddress)), "wrong CW contract address"); + return bytes(""); + } + + // Queries + function query(string memory, bytes memory) external pure returns (bytes memory) { + return bytes(""); + } +} + +contract MockJson is IJson { + function extractAsBytes(bytes memory, string memory) external pure returns (bytes memory) { + return bytes("extracted bytes"); + } + + function extractAsBytesList(bytes memory, string memory) external pure returns (bytes[] memory) { + return new bytes[](0); + } + + function extractAsUint256(bytes memory input, string memory key) external view returns (uint256 response) { + return 0; + } +} + +contract MockAddr is IAddr { + function getSeiAddr(address addr) external pure returns (string memory) { + if (addr == MockCallerEVMAddr) { + return MockCallerSeiAddr; + } + return MockOperatorSeiAddr; + } + + function getEvmAddr(string memory addr) external pure returns (address) { + if (keccak256(abi.encodePacked(addr)) == keccak256(abi.encodePacked(MockCallerSeiAddr))) { + return MockCallerEVMAddr; + } + return MockOperatorEVMAddr; + } +} + +contract CW1155ERC1155PointerTest is Test { + CW1155ERC1155Pointer pointer; + MockWasmd mockWasmd; + MockJson mockJson; + MockAddr mockAddr; + + function setUp() public { + pointer = new CW1155ERC1155Pointer(MockCWContractAddress, "ipfs://uri.json"); + mockWasmd = new MockWasmd(); + mockJson = new MockJson(); + mockAddr = new MockAddr(); + vm.etch(WASMD_PRECOMPILE_ADDRESS, address(mockWasmd).code); + vm.etch(JSON_PRECOMPILE_ADDRESS, address(mockJson).code); + vm.etch(ADDR_PRECOMPILE_ADDRESS, address(mockAddr).code); + } + + function testBalanceOf() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + assertEq(pointer.balanceOf(MockCallerEVMAddr, 1), 1); + } + + function testBalanceOfZeroAddress() public { + vm.expectRevert(bytes("ERC1155: cannot query balance of zero address")); + pointer.balanceOf(MockZeroAddress, 1); + } + + function testBalanceOfBatch() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"2\"}}")), + abi.encode("{\"balance\":\"2\"}") + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"3\"}}")), + abi.encode("{\"balance\":\"0\"}") + ); + + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"2\"}"), "balance"), + abi.encode(2) + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"0\"}"), "balance"), + abi.encode(0) + ); + address[] memory owners = new address[](3); + uint256[] memory ids = new uint256[](3); + owners[0] = MockCallerEVMAddr; + owners[1] = MockCallerEVMAddr; + owners[2] = MockCallerEVMAddr; + ids[0] = 1; + ids[1] = 2; + ids[2] = 3; + uint256[] memory expectedResp = new uint256[](3); + expectedResp[0] = 1; + expectedResp[1] = 2; + expectedResp[2] = 0; + assertEq(pointer.balanceOfBatch(owners, ids), expectedResp); + } + + function testBatchBalanceOfBadLength() public { + uint256 idsLength = 1; + uint256 valuesLength = 0; + vm.expectRevert( + abi.encodeWithSelector( + IERC1155Errors.ERC1155InvalidArrayLength.selector, + idsLength, + valuesLength + ) + ); + pointer.balanceOfBatch(new address[](valuesLength), new uint256[](idsLength)); + } + + function testUri() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"token_info\":{\"token_id\":\"1\"}}")), + abi.encode("{\"extension\": { \"animation_url\": null, \"attributes\": null, \"background_color\": null, \"description\": null, \"external_url\": null, \"image\": null, \"image_data\": null, \"name\": null, \"royalty_payment_address\": null, \"royalty_percentage\": null, \"youtube_url\": null }, \"token_uri\": \"test\" }") + ); + + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsBytes(bytes,string)", bytes("{\"extension\": { \"animation_url\": null, \"attributes\": null, \"background_color\": null, \"description\": null, \"external_url\": null, \"image\": null, \"image_data\": null, \"name\": null, \"royalty_payment_address\": null, \"royalty_percentage\": null, \"youtube_url\": null }, \"token_uri\": \"test\" }"), "token_uri"), + abi.encode(bytes("test")) + ); + assertEq(pointer.uri(1), "test"); + } + + function testIsApprovedForAll() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"is_approved_for_all\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"operator\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\"}}")), + abi.encode("{\"approved\":true}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"approved\":true}"), "approved"), + abi.encode(true) + ); + assertEq(pointer.isApprovedForAll(MockCallerEVMAddr, MockOperatorEVMAddr), true); + } +} \ No newline at end of file From 792da468d698c1fb26ed9e379126d1d2b3c066f7 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Thu, 20 Jun 2024 21:12:25 +0100 Subject: [PATCH 09/65] follow same coding style --- contracts/src/CW1155ERC1155Pointer.sol | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index caa15ae3d..7513fbacf 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -44,11 +44,9 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { // Queries function balanceOf(address account, uint256 id) public view override returns (uint256) { require(account != address(0), "ERC1155: cannot query balance of zero address"); - string memory req = _curlyBrace( - _keyValue("balance_of",(_curlyBrace( - _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))),",",_keyValue("token_id", _doubleQuotes(Strings.toString(id)))) - ))) - ); + string memory own = _formatPayload("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))); + string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(id))); + string memory req = _curlyBrace(_formatPayload("balance_of",(_curlyBrace(_join(own,",",tId))))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return JsonPrecompile.extractAsUint256(response, "balance"); } @@ -64,27 +62,22 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { } function uri(uint256 id) public view override returns (string memory) { - string memory req = _curlyBrace( - _keyValue("token_info",(_curlyBrace( - _keyValue("token_id", _doubleQuotes(Strings.toString(id))) - ))) - ); + string memory tId = _curlyBrace(_formatPayload("token_id", _doubleQuotes(Strings.toString(id)))); + string memory req = _curlyBrace(_formatPayload("token_info",(tId))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return string(JsonPrecompile.extractAsBytes(response, "token_uri")); } function isApprovedForAll(address owner, address operator) public view override returns (bool) { - string memory req = _curlyBrace( - _keyValue("is_approved_for_all",(_curlyBrace( - _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))),",",_keyValue("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator)))) - ))) - ); + string memory own = _formatPayload("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))); + string memory op = _formatPayload("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator))); + string memory req = _curlyBrace(_formatPayload("is_approved_for_all",(_curlyBrace(_join(own,",",op))))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return JsonPrecompile.extractAsUint256(response, "approved") == 1; } - function _keyValue(string memory key, string memory value) internal pure returns (string memory) { + function _formatPayload(string memory key, string memory value) internal pure returns (string memory) { return _join(_doubleQuotes(key), ":", value); } From 6304c6dd3eaa89328864331f701a186c47f6f819 Mon Sep 17 00:00:00 2001 From: davyli Date: Fri, 21 Jun 2024 07:52:30 -0400 Subject: [PATCH 10/65] Add cwerc1155.wasm binary to `/contracts` --- contracts/wasm/cwerc1155.wasm | Bin 0 -> 291992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 contracts/wasm/cwerc1155.wasm diff --git a/contracts/wasm/cwerc1155.wasm b/contracts/wasm/cwerc1155.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a905d5e616d419c5a8cc58396b969e0c0536b327 GIT binary patch literal 291992 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

L7&* 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ⓈgN@1^WSP;)LOB;F>qdk}IDvdpvkjTjtf zTYG7>8?OpT_>IAx$GmDBaM10Bt13GdYEv>{NIleR2lgE1-Ir{rCp26K?l)^-YwrL? zKxgL~OBtX>irDC#Y-7|gacCW)52-|DW8tTX8x5N*HWm|R?iqXi+|5dyzO#2&ihi=K zx7y#6Y}pbV<@E8%q~iM{1APN1MD_f6NoE`+LE_6UBo%MlGB3daIaE!$_zeuYcd$jW za_3M^{Iq9e7j_CIb7S9^bREWExUWS ziOkRf@ZnI`8tUo*XZky1P;PL9zc=chAzwObIL+bIJikl`CMDdcvvXu%FW%$1Cv8av z2jnW)vUX@_OM=ERQVkaIUcyhh@M3-oM}~(MA_%(r7j~o03@#k1UV>{6FMy2SOL}YD zN475L9^5&9QMJ2!`QlZpdbX~rcCTE#1jE>I!ug24`HL1TTd>$(Vankl9F}3f3HaVf z8^6O(W1QXp)`a_C_ zYPn=^&jejwWT(X~BQks?^)?Su@Xs3DLk)Wd(f@}AcMY=UgI8Q$8lIZ9?iUmWSZ>Pf z8!=?EyZftMta`|>AIFTnO>Y_Y&(7XU@E}&jRkhMY13P7r0gGEv@(*pntiNk33jRuW#t zm}m_3Tg|UaZhf(@WLsBnf3>GG*@@M7+AEXcYX7zc{ndfFCo!F+CMC7OWCt7##>W*) zjQ#j8^`b^Ap=5G;GBVuzR`keo)7QNuHZPR?)XZ{lHgMjt5&MVfW!3nk!Cf%ErcB4nipvmjFOI3*>*#+*J7;mNaaqq#uxGeF zhwF3soyYHm;(8hI;i_3ByUah*v+X9&Wwon7F}^tusup;_%tP9M&MtFr`G$#YnK z6SVcynN(GlnUg`5+qSW+n(W=qj6%G3kMyHnpgnIL*~Xe^q8awWg}<97^E(zSUbJ9^ zllud3rs~3-gFVc)^_kab(>j>^`HX>lSsL@#=$Dj(*OOk!PkKRiFTEh)*Ent$aDSoy zy>M`|(V3vD3_H#vW#tT(InmaJs$D&>EXR=GMVHjJ2f>@#onIs%eG{-qPD%D%fT{%F z+66OX%`fRi;Uh=@U669(F)um1JF7bfhxVCVzK1s6KpT>u(gi&%aA=gTq^oA2WT25h zvr;x+SoWUyx8A$R+f1f=btb_k%E?EQjUe+_q_i*D)is1-K|dEH-W!4@YhrS^GwDFh z>`4}(%=h!Y^rh_mT_anupR}}_u+&c=33+!@=GcZZ!@ZXbbg{C9jb%k1B40c?t7CiD z@b>KOC&`mv^(>?!5f;w9#eM55oR8lan14E(XC?A{AJKxXmnKU^V;K+H#I)^TiyNpyi zsP9Mp`T4#M#jHKgztbuAs-?@8uUNUN^VHK`>E8;%D9+`Z3dQD@Qfu3!$>k|W969x< zqmP+(tSc~m#?0f6pOv&%UNQTG6X(o5>Eu)9&0nyvW6|Oz&$HQ=w^+L7j5F7+JL~NA zuikLZx#w*>|1}p}xap#cU;Db(zoBbucTaWOCEI&<^!4u?7~Hj+XseMudoSJhRsrwu zaLPgiuBVM8Q>TJYpXkO`JS&s&Z{%A1^u@^dH}k&!UJe;Qd(Lh`Wg{ycSR2=0m`vC7TF!Z|=NUw5@V zd2Kb>4nQ;xW^ij%tzNT3U|JRcDf>hgqKvh9$xd6>p(><1!k3l?wH!7$P)&$mN_;DW z@+B^~8G0y2FN54C3?%cZ+;x)ksSHAQ(w#*AnH+ly*PHom;n&5lcVHK!RvR2l`b9fJ ziP&Ri`9W0;H%?~Ca0|{q*~y2)y$@Lo4&bd~8Ohbr_@JSlo2X}oU{O2UM|KiP`c@`| zqQ9)2FZy=8Lx0oYpwW1J25ra9Q5}E^gna(*V(MH1ecHfYeC~orcpvpL$Z#?O6ObP? zyMLd*_di`#KTnpi|N(SxgiTGZ(!PVyo6^C+S$QXxZU` z2hQuLJ8gjX(-YwT_JsRC^Y<@YuRN66u0EJb85HN0gNuMi`uco+W`#eSC4mz((~+}x z^}cjFmXn2{;BM+pSXE}FQ~rCEIl_-k>Ga9Nbme(QqhDfD-~6; z%-lg%_#yJ86KCa2oNiM@Ip_RjDk3cVc=FT&mgPNLXdb@Ja0T%yLOE-c&H zzUKwVic1k1F856Gq-SS&awD64+*w~hdSycJ*+^IaE4NTqaRrx=N{7teSz~^qdX>RV z=Xd`0?(!EdP5_@K9X%z$N9I(m(G1L7|d1#vfL-g6P#mXm5snK(zClNy2P#?vA;KVApF-mWs$Qfs-#-G>LV2o%Wy}% zgZO^6?SOeR9)@1ZS=K<$BA+fkc-*Xpaj?CW_e`J52;0rQZ1M&F3JlUYe@QC(YaHV- zcm{gjNdD{iUBvGKejE9n!|%6vC*xI@as4)aFNRlL&ind%Ie69Wi^ucdgVukSxVbc$ zRP7&Xtu`TV3VB%>Z-}Cu`n6gXf-@>iD0ikWe-WwhG;y6cTer>1)hH)k6_DyLv*W9x z4d(mpJlA~pl#D6 zq5L1ugw09K0 z^MFvYC%y2D_3INN<+KwDJI0H*;Omq>j&j+1zr(fg^D@Ee+_lvI4DHI65I?9i-0$al z9>2?$yYYMVg&WUfO7vTkFBJJ$jwV?i@tj4|D zdy&yZ1hO>DW*_K!Ju>sgX>Sur+& zY{l@)Zr!-!KgK_XDX?IzkIi@HW4(id#2mG>Yw)^Wj+MshHNRbz6)_Oem29c80S#8P z#ij`tGUbvjayM^zwpP^pdL47-%^@PdUYzr`ISua#v3tkxn#?`(jE;`KAASFs>(;G1 z={Kz&u;#pZeC@Kh$5p@5RlnxBt5e<%pE)QU zW;VaTezOyaDNZi;w4%B|Kj?HhWmvGQRz4T4SlQgo$a0FK)TXu zeu6!_U&FOv&+f0`I%&ASmTU3UEdN%nS4_BH_l@~CbHAEj_WlPa z9-$yE0^es~9Fl#er#n!Nl zhgk?wSF(Km)?Tep?d(!G(9nY5ao#zFcQP1c_$1sfitl zJi|(dcz5>*!(#Yp+K}Fpwe@zcH8-+*jqi)o z5e_xagJ$2mo2w|vEaX9eyKv)m2XkptzMdapgouZ{gP-gX>6DtQnxF6F zmpxNIuj8kD{jTTt9)36Q%i`Bu$jQX`wPXuAQ`N_>xfRgFVwcV863+ai zZA|$$@%wFljb+5k#IN*Bf1(}nGs%Yx|Dx~THrKhqJ7`0r!NRKsvv6}TEZcV0 zfa59J(%ALTmT>yBuYUQYgUbT5C*PBj;q8MXgbkw-5tXDcqq!)5Te@mn2)`r{69&Oi z1NQL3)X~prq{mSAEK=bxAyxlYF&L5+jd+v%G5%w`b$p&=&pH-o z;xtr=6os4E%8XmPaSGB&3l;>QS>yOu;84q!AI;XSau5+Sp!ua?U=(agO!uxJPl7+< z-2}Y-4XOA`C%qvV)@GDt5$TZShQmCiX|(Su2{BW`HB@QR<2mJvSa0UFR~)6?yZJQsy#`R;vJ`&eL(5j!tg zlumFD?+E^Hl8UE<|HFSlddKzm2c;#^v;M^s{&M;Y(#Q4ccaM7Gf&~lSY|5y|EE9U% zf8-Hz$7t>x52EK#ci!&=fv<~p76B!eh}XFGMBNL}wCmE8RRsr&%#2^hhbYkIxWOWxhHw=1X9!&lQG%-bnfT!3&J>`Z)%DPO~pd< zl$M#LV_T=Ul_#}M&XwaMjySUU=m-$~szm5+yf9BGC@4o(H9j|@eyRW-(=JzK}-f+$@pINZ*Rd0Ip=D)xC z`uDu|eV_dNm;U%0-~85}{@vq0IuPWh9C6a3r7Jp5edYRBzxnF-koko#{qZ;d^e-NK z{6|5qZIb17p1OA3`d7cDr+W2!fA_=R`ilqKrkup1^{;*7o8Cf@_Vw@mB(HqqTR(XG zM^Cm*S-ZZcI(qf*-TRfV{?&J%{I{##{_flF_{vwm@h1=d?f1^U`OAO)&A)hX{dpT- z`}((Re&>5``1~LI;aBhf=AV3b%F)NX@lC(@&tD%H-MRbkelTg)z~Ic|Hoxui&wlQT zKfd?qV~(G-?yU1RzU~cgdduZk{Qfr{{;Nly{I~xY8or@6@_`cOfr-uT`NFBy5@TMvEbk-z!z zuMY&t=E{{n$X$76aYn9b%Kp12jea^mt9k#7_}F5YTbNs#E5u=;sW7GG{K-cYE-J*i znJvw6F)nb5WgNHW@^PstoOD$FyuysaYYS1+F|Ft4&WPv7VQxy(1RQPk=)0OeeS7OMxkVq%?f=^o3$6M5=pE(#|4|5&lbguBJ~#T6ct$+A zE#QcFIv3>&g{W9;j#~1iXi}~mPKl1lA30@ecvN&ubZpzq{Bgxu;p}int}psr{Q2nK z=)vea(Zj8O)%@4dccZ@zAItwR`f=_j(NB{nb5BSAH~wYVI_K2W&)ayzt+#&Ux8D8! z4}9$RzVwdIHx-(fzw-2p|NWuwpc+<2qlp_BD6h`RzZyt#Iu0$_b~x>c>y~ z?7%m^nM+=A!ijU2tn57d)#sdl;YAmV_O^6axAhHQ`nD_Hb^E72ch7wfefDz$gI{_7 zTPnYmk8|_mZE?78!RVF8#fv7-%*}2-K7UI7%-p1tM?cjxJ2yKwx45))-WmH>G#}kk zoObHkRdIK*x#MU~ZJv=2SFg-%$S=&b6q*aGlR3H8=H+o`etIF-S~!3GiY0AJ3JZ!Y z`%k=J!zsm+kDh+w%&EsTpGN~{wjEn&X*#<&r+K8b=Jb=BPR+M8y{0M5m*f2CySE;H zcClsjj<;0SmRg$Hj_hn|Sw1g!%;+DT)^lO&+08BM*3LM)cwyW6Ld)nc*0mfLpS6BP zJgL~yw5rgufBCV6Q{$Nzhm#k#UG=-$MoOb!f7dzPZC7`ckG|nkSDy9JKe}>N;pE(# znoew4*D^PMNaBM}7q9;7lbb*GCw@=;fxKdY%}^si3IpWYtsnjcTk zMf+FJn$npM_dj&nxt`XGTSh;- z^0>Bnxn^cW)98n;dL%a`Zj1NkHa9W9Cb#BR(z&_C%6a=YwH^m7%ZrmJ+FTg@vlCjb zZaORv_q^PW=7NnYoJzK8qkeM_tlM<{y7G^+x3_2W$S#frGFxFY+QoRC==0+DD6UuK zlHk4hEy0_Qye&B5m}FLKvSrrK=G}J6$sNhO!8;zC7u~gG{_(%uvLN_%vi#NqTbBPS z{NeJjrG3ThwjZwe^rWs;3#WZ_RmaS(v;Y10kDjx7Y1jEr?)d0yHV(F5@ZozudO`4D z*M-&ZeDuQLZ`(HokNxnX&;EVaYoB<${q+z1jte{Wdag*3 zmS}nyMXTTvxd<*99v{V=cFcXA0^!u?Xm|*vsk;~!;+E+6@KoMy<;}TNPpxqt7E_2y zR;xgw(Mb0*qgB9{wQ^i|c9X7)Re+9fbe8J&3Olw#NW21cd!D#vsZQ+TJ_qocYVF!X_4G3(?AAZ5CD*t=2^rwi8sa)ZL*$tedca>K&Gj&Mk;*=dARM7Y>*JQLfO3;@0O!m$b0v~H z`$ Date: Fri, 21 Jun 2024 08:51:49 -0400 Subject: [PATCH 11/65] Add go code to support new pointer contract --- contracts/test/lib.js | 10 ++ .../scripts/evm_interoperability_tests.sh | 2 + precompiles/common/expected_keepers.go | 2 + precompiles/pointer/Pointer.sol | 4 + precompiles/pointer/abi.json | 2 +- precompiles/pointer/pointer.go | 61 ++++++++ precompiles/pointerview/Pointerview.sol | 4 + precompiles/pointerview/abi.json | 2 +- precompiles/pointerview/pointerview.go | 15 ++ precompiles/pointerview/pointerview_test.go | 17 ++ precompiles/wasmd/wasmd.go | 6 +- proto/evm/enums.proto | 2 + proto/evm/gov.proto | 24 +++ x/evm/artifacts/cw1155/artifacts.go | 88 +++++++++++ x/evm/artifacts/erc1155/artifacts.go | 2 +- x/evm/client/cli/gov_tx.go | 106 +++++++++++++ x/evm/client/cli/native_tx.go | 6 +- x/evm/client/cli/query.go | 47 +++++- x/evm/client/cli/tx.go | 2 + x/evm/gov.go | 24 +++ x/evm/gov_test.go | 65 ++++++++ x/evm/handler.go | 4 + x/evm/keeper/genesis.go | 10 ++ x/evm/keeper/grpc_query.go | 25 +++ x/evm/keeper/grpc_query_test.go | 12 ++ x/evm/keeper/msg_server.go | 12 ++ x/evm/keeper/msg_server_test.go | 48 +++++- x/evm/keeper/pointer.go | 75 +++++++++ x/evm/keeper/pointer_test.go | 145 ++++++++++++++++++ x/evm/migrations/store_cw_pointer_code.go | 14 +- x/evm/module.go | 6 +- x/evm/types/codec.go | 2 + x/evm/types/enums.pb.go | 26 ++-- x/evm/types/gov.go | 83 ++++++++++ x/evm/types/keys.go | 26 +++- x/evm/types/message_register_pointer.go | 4 + 36 files changed, 954 insertions(+), 29 deletions(-) create mode 100644 x/evm/artifacts/cw1155/artifacts.go diff --git a/contracts/test/lib.js b/contracts/test/lib.js index ddf6e546e..7eb52df6f 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -41,6 +41,7 @@ const WASM = { CW20: "../contracts/wasm/cw20_base.wasm", POINTER_CW20: "../example/cosmwasm/cw20/artifacts/cwerc20.wasm", POINTER_CW721: "../example/cosmwasm/cw721/artifacts/cwerc721.wasm", + POINTER_CW1155: "../example/cosmwasm/cw721/artifacts/cwerc1155.wasm", } function sleep(ms) { @@ -315,6 +316,15 @@ async function registerPointerForERC721(erc721Address, fees="20000usei", from=ad return getEventAttribute(response, "pointer_registered", "pointer_address") } +async function registerPointerForERC1155(erc1155Address, fees="20000usei", from=adminKeyName) { + const command = `seid tx evm register-cw-pointer ERC1155 ${erc1155Address} --from ${from} --fees ${fees} --broadcast-mode block -y -o json` + const output = await execute(command); + const response = JSON.parse(output) + if(response.code !== 0) { + throw new Error("contract deployment failed") + } + return getEventAttribute(response, "pointer_registered", "pointer_address") +} async function getSeiAddress(evmAddress) { const command = `seid q evm sei-addr ${evmAddress} -o json` diff --git a/integration_test/evm_module/scripts/evm_interoperability_tests.sh b/integration_test/evm_module/scripts/evm_interoperability_tests.sh index 2dc58ab62..dadc719c2 100755 --- a/integration_test/evm_module/scripts/evm_interoperability_tests.sh +++ b/integration_test/evm_module/scripts/evm_interoperability_tests.sh @@ -9,3 +9,5 @@ npx hardhat test --network seilocal test/ERC20toCW20PointerTest.js npx hardhat test --network seilocal test/ERC20toNativePointerTest.js npx hardhat test --network seilocal test/CW721toERC721PointerTest.js npx hardhat test --network seilocal test/ERC721toCW721PointerTest.js +npx hardhat test --network seilocal test/CW1155toERC1155PointerTest.js +npx hardhat test --network seilocal test/ERC1155toCW1155PointerTest.js diff --git a/precompiles/common/expected_keepers.go b/precompiles/common/expected_keepers.go index 6239cc827..973315166 100644 --- a/precompiles/common/expected_keepers.go +++ b/precompiles/common/expected_keepers.go @@ -39,6 +39,8 @@ type EVMKeeper interface { GetERC20CW20Pointer(ctx sdk.Context, cw20Address string) (addr common.Address, version uint16, exists bool) SetERC721CW721Pointer(ctx sdk.Context, cw721Address string, addr common.Address) error GetERC721CW721Pointer(ctx sdk.Context, cw721Address string) (addr common.Address, version uint16, exists bool) + SetERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string, addr common.Address) error + GetERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string) (addr common.Address, version uint16, exists bool) } type OracleKeeper interface { diff --git a/precompiles/pointer/Pointer.sol b/precompiles/pointer/Pointer.sol index a9575b5d5..b1d9fb4e0 100644 --- a/precompiles/pointer/Pointer.sol +++ b/precompiles/pointer/Pointer.sol @@ -17,4 +17,8 @@ interface IPointer { function addCW721Pointer( string memory cwAddr ) external returns (address ret); + + function addCW1155Pointer( + string memory cwAddr + ) external returns (address ret); } diff --git a/precompiles/pointer/abi.json b/precompiles/pointer/abi.json index 8fb8238da..6f96c1959 100644 --- a/precompiles/pointer/abi.json +++ b/precompiles/pointer/abi.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"addCW20Pointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"addCW721Pointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"token","type":"string"}],"name":"addNativePointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"addCW1155Pointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"addCW20Pointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"addCW721Pointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"token","type":"string"}],"name":"addNativePointer","outputs":[{"internalType":"address","name":"ret","type":"address"}],"stateMutability":"payable","type":"function"}] \ No newline at end of file diff --git a/precompiles/pointer/pointer.go b/precompiles/pointer/pointer.go index 2e274ddca..9c8a7886d 100644 --- a/precompiles/pointer/pointer.go +++ b/precompiles/pointer/pointer.go @@ -18,6 +18,7 @@ import ( "github.com/sei-protocol/sei-chain/utils" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -28,6 +29,7 @@ const ( AddNativePointer = "addNativePointer" AddCW20Pointer = "addCW20Pointer" AddCW721Pointer = "addCW721Pointer" + AddCW1155Pointer = "addCW1155Pointer" ) const PointerAddress = "0x000000000000000000000000000000000000100b" @@ -50,6 +52,7 @@ type Precompile struct { AddNativePointerID []byte AddCW20PointerID []byte AddCW721PointerID []byte + AddCW1155PointerID []byte } func ABI() (*ethabi.ABI, error) { @@ -87,6 +90,8 @@ func NewPrecompile(evmKeeper pcommon.EVMKeeper, bankKeeper pcommon.BankKeeper, w p.AddCW20PointerID = m.ID case AddCW721Pointer: p.AddCW721PointerID = m.ID + case AddCW1155Pointer: + p.AddCW1155PointerID = m.ID } } @@ -131,6 +136,8 @@ func (p Precompile) RunAndCalculateGas(evm *vm.EVM, caller common.Address, calli return p.AddCW20(ctx, method, caller, args, value, evm, suppliedGas) case AddCW721Pointer: return p.AddCW721(ctx, method, caller, args, value, evm, suppliedGas) + case AddCW1155Pointer: + return p.AddCW1155(ctx, method, caller, args, value, evm, suppliedGas) default: err = fmt.Errorf("unknown method %s", method.Name) } @@ -305,3 +312,57 @@ func (p Precompile) AddCW721(ctx sdk.Context, method *ethabi.Method, caller comm ret, err = method.Outputs.Pack(contractAddr) return } + +func (p Precompile) AddCW1155(ctx sdk.Context, method *ethabi.Method, caller common.Address, args []interface{}, value *big.Int, evm *vm.EVM, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) { + if err := pcommon.ValidateNonPayable(value); err != nil { + return nil, 0, err + } + if err := pcommon.ValidateArgsLength(args, 1); err != nil { + return nil, 0, err + } + cwAddr := args[0].(string) + existingAddr, existingVersion, exists := p.evmKeeper.GetERC1155CW1155Pointer(ctx, cwAddr) + if exists && existingVersion >= cw1155.CurrentVersion { + return nil, 0, fmt.Errorf("pointer at %s with version %d exists when trying to set pointer for version %d", existingAddr.Hex(), existingVersion, cw1155.CurrentVersion) + } + cwAddress, err := sdk.AccAddressFromBech32(cwAddr) + if err != nil { + return nil, 0, err + } + res, err := p.wasmdKeeper.QuerySmart(ctx, cwAddress, []byte("{\"contract_info\":{}}")) + if err != nil { + return nil, 0, err + } + formattedRes := map[string]interface{}{} + if err := json.Unmarshal(res, &formattedRes); err != nil { + return nil, 0, err + } + name := formattedRes["name"].(string) + symbol := formattedRes["symbol"].(string) + constructorArguments := []interface{}{ + cwAddr, name, symbol, + } + + packedArgs, err := cw1155.GetParsedABI().Pack("", constructorArguments...) + if err != nil { + panic(err) + } + bin := append(cw1155.GetBin(), packedArgs...) + if value == nil { + value = utils.Big0 + } + ret, contractAddr, remainingGas, err := evm.Create(vm.AccountRef(caller), bin, suppliedGas, value) + if err != nil { + return + } + err = p.evmKeeper.SetERC1155CW1155Pointer(ctx, cwAddr, contractAddr) + if err != nil { + return + } + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "cw1155"), + sdk.NewAttribute(types.AttributeKeyPointerAddress, contractAddr.Hex()), sdk.NewAttribute(types.AttributeKeyPointee, cwAddr), + sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", cw1155.CurrentVersion)))) + ret, err = method.Outputs.Pack(contractAddr) + return +} diff --git a/precompiles/pointerview/Pointerview.sol b/precompiles/pointerview/Pointerview.sol index 497c977fd..4053ce6ba 100644 --- a/precompiles/pointerview/Pointerview.sol +++ b/precompiles/pointerview/Pointerview.sol @@ -17,4 +17,8 @@ interface IPointerview { function getCW721Pointer( string memory cwAddr ) view external returns (address addr, uint16 version, bool exists); + + function getCW1155Pointer( + string memory cwAddr + ) view external returns (address addr, uint16 version, bool exists); } diff --git a/precompiles/pointerview/abi.json b/precompiles/pointerview/abi.json index a469eff12..c089390d1 100644 --- a/precompiles/pointerview/abi.json +++ b/precompiles/pointerview/abi.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"getCW20Pointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"getCW721Pointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"token","type":"string"}],"name":"getNativePointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"getCW1155Pointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"getCW20Pointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"cwAddr","type":"string"}],"name":"getCW721Pointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"token","type":"string"}],"name":"getNativePointer","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/precompiles/pointerview/pointerview.go b/precompiles/pointerview/pointerview.go index f56e8ce05..c603cde23 100644 --- a/precompiles/pointerview/pointerview.go +++ b/precompiles/pointerview/pointerview.go @@ -18,6 +18,7 @@ const ( GetNativePointer = "getNativePointer" GetCW20Pointer = "getCW20Pointer" GetCW721Pointer = "getCW721Pointer" + GetCW1155Pointer = "getCW1155Pointer" ) const PointerViewAddress = "0x000000000000000000000000000000000000100A" @@ -37,6 +38,7 @@ type Precompile struct { GetNativePointerID []byte GetCW20PointerID []byte GetCW721PointerID []byte + GetCW1155PointerID []byte } func NewPrecompile(evmKeeper pcommon.EVMKeeper) (*Precompile, error) { @@ -64,6 +66,8 @@ func NewPrecompile(evmKeeper pcommon.EVMKeeper) (*Precompile, error) { p.GetCW20PointerID = m.ID case GetCW721Pointer: p.GetCW721PointerID = m.ID + case GetCW1155Pointer: + p.GetCW1155PointerID = m.ID } } @@ -101,6 +105,8 @@ func (p Precompile) Run(evm *vm.EVM, _ common.Address, _ common.Address, input [ return p.GetCW20(ctx, method, args) case GetCW721Pointer: return p.GetCW721(ctx, method, args) + case GetCW1155Pointer: + return p.GetCW1155(ctx, method, args) default: err = fmt.Errorf("unknown method %s", method.Name) } @@ -133,3 +139,12 @@ func (p Precompile) GetCW721(ctx sdk.Context, method *abi.Method, args []interfa existingAddr, existingVersion, exists := p.evmKeeper.GetERC721CW721Pointer(ctx, addr) return method.Outputs.Pack(existingAddr, existingVersion, exists) } + +func (p Precompile) GetCW1155(ctx sdk.Context, method *abi.Method, args []interface{}) (ret []byte, err error) { + if err := pcommon.ValidateArgsLength(args, 1); err != nil { + return nil, err + } + addr := args[0].(string) + existingAddr, existingVersion, exists := p.evmKeeper.GetERC1155CW1155Pointer(ctx, addr) + return method.Outputs.Pack(existingAddr, existingVersion, exists) +} diff --git a/precompiles/pointerview/pointerview_test.go b/precompiles/pointerview/pointerview_test.go index a520878c4..c987dae3b 100644 --- a/precompiles/pointerview/pointerview_test.go +++ b/precompiles/pointerview/pointerview_test.go @@ -8,6 +8,7 @@ import ( testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/stretchr/testify/require" ) @@ -20,6 +21,7 @@ func TestPointerView(t *testing.T) { k.SetERC20NativePointer(ctx, "test", pointer) k.SetERC20CW20Pointer(ctx, "test", pointer) k.SetERC721CW721Pointer(ctx, "test", pointer) + k.SetERC1155CW1155Pointer(ctx, "test", pointer) m, err := p.ABI.MethodById(p.GetNativePointerID) require.Nil(t, err) ret, err := p.GetNative(ctx, m, []interface{}{"test"}) @@ -64,4 +66,19 @@ func TestPointerView(t *testing.T) { outputs, err = m.Outputs.Unpack(ret) require.Nil(t, err) require.False(t, outputs[2].(bool)) + + m, err = p.ABI.MethodById(p.GetCW1155PointerID) + require.Nil(t, err) + ret, err = p.GetCW1155(ctx, m, []interface{}{"test"}) + require.Nil(t, err) + outputs, err = m.Outputs.Unpack(ret) + require.Nil(t, err) + require.Equal(t, pointer, outputs[0].(common.Address)) + require.Equal(t, cw1155.CurrentVersion, outputs[1].(uint16)) + require.True(t, outputs[2].(bool)) + ret, err = p.GetCW1155(ctx, m, []interface{}{"test2"}) + require.Nil(t, err) + outputs, err = m.Outputs.Unpack(ret) + require.Nil(t, err) + require.False(t, outputs[2].(bool)) } diff --git a/precompiles/wasmd/wasmd.go b/precompiles/wasmd/wasmd.go index 766164f3d..11450e6f9 100644 --- a/precompiles/wasmd/wasmd.go +++ b/precompiles/wasmd/wasmd.go @@ -319,7 +319,8 @@ func (p Precompile) executeBatch(ctx sdk.Context, method *abi.Method, caller com if caller.Cmp(callingContract) != 0 { erc20pointer, _, erc20exists := p.evmKeeper.GetERC20CW20Pointer(ctx, contractAddrStr) erc721pointer, _, erc721exists := p.evmKeeper.GetERC721CW721Pointer(ctx, contractAddrStr) - if (!erc20exists || erc20pointer.Cmp(callingContract) != 0) && (!erc721exists || erc721pointer.Cmp(callingContract) != 0) { + erc1155pointer, _, erc1155exists := p.evmKeeper.GetERC1155CW1155Pointer(ctx, contractAddrStr) + if (!erc20exists || erc20pointer.Cmp(callingContract) != 0) && (!erc721exists || erc721pointer.Cmp(callingContract) != 0) && (!erc1155exists || erc1155pointer.Cmp(callingContract) != 0) { return nil, 0, fmt.Errorf("%s is not a pointer of %s", callingContract.Hex(), contractAddrStr) } } @@ -412,7 +413,8 @@ func (p Precompile) execute(ctx sdk.Context, method *abi.Method, caller common.A if caller.Cmp(callingContract) != 0 { erc20pointer, _, erc20exists := p.evmKeeper.GetERC20CW20Pointer(ctx, contractAddrStr) erc721pointer, _, erc721exists := p.evmKeeper.GetERC721CW721Pointer(ctx, contractAddrStr) - if (!erc20exists || erc20pointer.Cmp(callingContract) != 0) && (!erc721exists || erc721pointer.Cmp(callingContract) != 0) { + erc1155pointer, _, erc1155exists := p.evmKeeper.GetERC721CW721Pointer(ctx, contractAddrStr) + if (!erc20exists || erc20pointer.Cmp(callingContract) != 0) && (!erc721exists || erc721pointer.Cmp(callingContract) != 0) && (!erc1155exists || erc1155pointer.Cmp(callingContract) != 0) { return nil, 0, fmt.Errorf("%s is not a pointer of %s", callingContract.Hex(), contractAddrStr) } } diff --git a/proto/evm/enums.proto b/proto/evm/enums.proto index fefdee9ab..d3cc8c71a 100644 --- a/proto/evm/enums.proto +++ b/proto/evm/enums.proto @@ -9,4 +9,6 @@ enum PointerType { NATIVE = 2; CW20 = 3; CW721 = 4; + ERC1155 = 5; + CW1155 = 6; } \ No newline at end of file diff --git a/proto/evm/gov.proto b/proto/evm/gov.proto index 55ec172d4..41efa6000 100644 --- a/proto/evm/gov.proto +++ b/proto/evm/gov.proto @@ -41,6 +41,18 @@ message AddERCCW721PointerProposal { uint32 version = 5 [(gogoproto.moretags) = "yaml:\"version\""]; } +message AddERCCW1155PointerProposal { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ]; + string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + string pointee = 3 [(gogoproto.moretags) = "yaml:\"pointee\""]; + string pointer = 4 [(gogoproto.moretags) = "yaml:\"pointer\""]; + uint32 version = 5 [(gogoproto.moretags) = "yaml:\"version\""]; +} + message AddCWERC20PointerProposal { option (gogoproto.equal) = false; option (gogoproto.goproto_getters) = false; @@ -64,3 +76,15 @@ message AddCWERC721PointerProposal { string pointer = 4 [(gogoproto.moretags) = "yaml:\"pointer\""]; uint32 version = 5 [(gogoproto.moretags) = "yaml:\"version\""]; } + +message AddCWERC1155PointerProposal { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ]; + string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ]; + string pointee = 3 [(gogoproto.moretags) = "yaml:\"pointee\""]; + string pointer = 4 [(gogoproto.moretags) = "yaml:\"pointer\""]; + uint32 version = 5 [(gogoproto.moretags) = "yaml:\"version\""]; +} diff --git a/x/evm/artifacts/cw1155/artifacts.go b/x/evm/artifacts/cw1155/artifacts.go new file mode 100644 index 000000000..3dd91308e --- /dev/null +++ b/x/evm/artifacts/cw1155/artifacts.go @@ -0,0 +1,88 @@ +package cw1155 + +import ( + "bytes" + "embed" + "encoding/hex" + "fmt" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" // TODO: delete +) + +const CurrentVersion uint16 = 1 + +// //go:embed CW1155ERC1155Pointer.abi +// //go:embed CW1155ERC1155Pointer.bin +var f embed.FS + +var cachedBin []byte +var cachedLegacyBin []byte +var cachedABI *abi.ABI + +func GetABI() []byte { + // bz, err := f.ReadFile("CW1155ERC1155Pointer.abi") + bz, err := f.ReadFile("../cw721/CW721ERC721Pointer.abi") // TODO: remove this line and uncomment line above + if err != nil { + panic("failed to read CW1155ERC1155Pointer contract ABI") + } + return bz +} + +func GetParsedABI() *abi.ABI { + if cachedABI != nil { + return cachedABI + } + parsedABI, err := abi.JSON(strings.NewReader(string(GetABI()))) + if err != nil { + panic(err) + } + cachedABI = &parsedABI + return cachedABI +} + +func GetBin() []byte { + if cachedBin != nil { + return cachedBin + } + // code, err := f.ReadFile("CW1155ERC1155Pointer.bin") + code, err := f.ReadFile("../cw721/CW721ERC721Pointer.bin") // TODO: remove this line and uncomment line above + if err != nil { + panic("failed to read CW1155ERC1155Pointer contract binary") + } + bz, err := hex.DecodeString(string(code)) + if err != nil { + panic("failed to decode CW1155ERC1155Pointer contract binary") + } + cachedBin = bz + return bz +} + +func IsCodeFromBin(code []byte) bool { + return isCodeFromBin(code, GetBin()) +} + +func isCodeFromBin(code []byte, bin []byte) bool { + binLen := len(bin) + if len(code) < binLen { + return false + } + if !bytes.Equal(code[:binLen], bin) { + return false + } + // abi, err := Cw1155MetaData.GetAbi() + abi, err := cw721.Cw721MetaData.GetAbi() // TODO: remove this line and uncomment line above + if err != nil { + fmt.Printf("error getting metadata ABI: %s\n", err) + return false + } + args, err := abi.Constructor.Inputs.Unpack(code[binLen:]) + if err != nil || len(args) != 3 { + return false + } + _, isA0String := args[0].(string) + _, isA1String := args[1].(string) + _, isA2String := args[2].(string) + return isA0String && isA1String && isA2String +} diff --git a/x/evm/artifacts/erc1155/artifacts.go b/x/evm/artifacts/erc1155/artifacts.go index daefb4010..4b3d8740c 100644 --- a/x/evm/artifacts/erc1155/artifacts.go +++ b/x/evm/artifacts/erc1155/artifacts.go @@ -1,4 +1,4 @@ -package erc721 +package erc1155 import "embed" diff --git a/x/evm/client/cli/gov_tx.go b/x/evm/client/cli/gov_tx.go index efc771b6d..59ddb6c3e 100644 --- a/x/evm/client/cli/gov_tx.go +++ b/x/evm/client/cli/gov_tx.go @@ -174,6 +174,59 @@ func NewAddERCCW721PointerProposalTxCmd() *cobra.Command { return cmd } +func NewAddERCCW1155PointerProposalTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "add-erc-cw1155-pointer title description cw1155address version deposit [pointer address]", + Args: cobra.RangeArgs(5, 6), + Short: "Submit an add ERC-CW1155 pointer proposal", + Long: strings.TrimSpace(` + Submit a proposal to register an ERC pointer contract address for a CW1155 token. + Not specifying the pointer address means a proposal that deletes the existing pointer. + `), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + version, err := strconv.ParseUint(args[3], 10, 16) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(args[4]) + if err != nil { + return err + } + var pointer string + if len(args) == 6 { + pointer = args[5] + } + + // Convert proposal to RegisterPairsProposal Type + from := clientCtx.GetFromAddress() + + content := types.AddERCCW1155PointerProposal{ + Title: args[0], + Description: args[1], + Pointee: args[2], + Version: uint32(version), + Pointer: pointer, + } + + msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, from) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + func NewAddCWERC20PointerProposalTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: "add-cw-erc20-pointer title description erc20address version deposit [pointer address]", @@ -279,3 +332,56 @@ func NewAddCWERC721PointerProposalTxCmd() *cobra.Command { return cmd } + +func NewAddCWERC1155PointerProposalTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "add-cw-erc1155-pointer title description erc1155address version deposit [pointer address]", + Args: cobra.RangeArgs(5, 6), + Short: "Submit an add CW-ERC1155 pointer proposal", + Long: strings.TrimSpace(` + Submit a proposal to register an CW pointer contract address for a ERC1155 token. + Not specifying the pointer address means a proposal that deletes the existing pointer. + `), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + version, err := strconv.ParseUint(args[3], 10, 16) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(args[4]) + if err != nil { + return err + } + var pointer string + if len(args) == 6 { + pointer = args[5] + } + + // Convert proposal to RegisterPairsProposal Type + from := clientCtx.GetFromAddress() + + content := types.AddCWERC1155PointerProposal{ + Title: args[0], + Description: args[1], + Pointee: args[2], + Version: uint32(version), + Pointer: pointer, + } + + msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, from) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/evm/client/cli/native_tx.go b/x/evm/client/cli/native_tx.go index b08518455..582bba3ab 100644 --- a/x/evm/client/cli/native_tx.go +++ b/x/evm/client/cli/native_tx.go @@ -59,7 +59,7 @@ func NativeSendTxCmd() *cobra.Command { func RegisterCwPointerCmd() *cobra.Command { cmd := &cobra.Command{ Use: "register-cw-pointer [pointer type] [erc address]", - Short: `Register a CosmWasm pointer for an ERC20/721 contract. Pointer type is either ERC20 or ERC721.`, + Short: `Register a CosmWasm pointer for an ERC20/721/1155 contract. Pointer type is either ERC20, ERC721, or ERC1155.`, Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) @@ -88,7 +88,7 @@ func RegisterCwPointerCmd() *cobra.Command { func RegisterEvmPointerCmd() *cobra.Command { cmd := &cobra.Command{ Use: "register-evm-pointer [pointer type] [cw-address] --gas-fee-cap= --gas-limit= --evm-rpc=", - Short: `Register an EVM pointer for a CosmWasm contract. Pointer type is either CW20, CW721, or NATIVE.`, + Short: `Register an EVM pointer for a CosmWasm contract. Pointer type is either CW20, CW721, CW1155, or NATIVE.`, Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { pInfo := precompiles.GetPrecompileInfo(pointer.PrecompileName) @@ -99,6 +99,8 @@ func RegisterEvmPointerCmd() *cobra.Command { payload, err = getMethodPayload(pInfo.ABI, []string{pointer.AddCW20Pointer, args[1]}) case "CW721": payload, err = getMethodPayload(pInfo.ABI, []string{pointer.AddCW721Pointer, args[1]}) + case "CW1155": + payload, err = getMethodPayload(pInfo.ABI, []string{pointer.AddCW1155Pointer, args[1]}) case "NATIVE": payload, err = getMethodPayload(pInfo.ABI, []string{pointer.AddNativePointer, args[1]}) default: diff --git a/x/evm/client/cli/query.go b/x/evm/client/cli/query.go index ad8806f81..a622abf5b 100644 --- a/x/evm/client/cli/query.go +++ b/x/evm/client/cli/query.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/sei-protocol/sei-chain/x/evm/types" ) @@ -40,6 +41,7 @@ func GetQueryCmd(_ string) *cobra.Command { cmd.AddCommand(CmdQueryEVMAddress()) cmd.AddCommand(CmdQueryERC20Payload()) cmd.AddCommand(CmdQueryERC721Payload()) + cmd.AddCommand(CmdQueryERC1155Payload()) cmd.AddCommand(CmdQueryERC20()) cmd.AddCommand(CmdQueryPayload()) cmd.AddCommand(CmdQueryPointer()) @@ -291,10 +293,53 @@ func CmdQueryERC721Payload() *cobra.Command { return cmd } +func CmdQueryERC1155Payload() *cobra.Command { + cmd := &cobra.Command{ + Use: "erc1155-payload [method] [arguments...]", + Short: "get hex payload for the given inputs", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return err + } + var bz []byte + switch args[0] { // TODO: fill in with key ERC1155 functions + case "approve": + spender := common.HexToAddress(args[1]) + id, _ := sdk.NewIntFromString(args[2]) + bz, err = abi.Pack(args[0], spender, id.BigInt()) + case "transferFrom": + from := common.HexToAddress(args[1]) + to := common.HexToAddress(args[2]) + id, _ := sdk.NewIntFromString(args[3]) + bz, err = abi.Pack(args[0], from, to, id.BigInt()) + case "setApprovalForAll": + op := common.HexToAddress(args[1]) + approved := args[2] == "true" + bz, err = abi.Pack(args[0], op, approved) + } + if err != nil { + return err + } + + return clientCtx.PrintString(hex.EncodeToString(bz)) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + func CmdQueryPointer() *cobra.Command { cmd := &cobra.Command{ Use: "pointer [type] [pointee]", - Short: "get pointer address of the specified type (one of [NATIVE, CW20, CW721, ERC20, ERC721]) and pointee", + Short: "get pointer address of the specified type (one of [NATIVE, CW20, CW721, CW1155, ERC20, ERC721, ERC1155]) and pointee", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) diff --git a/x/evm/client/cli/tx.go b/x/evm/client/cli/tx.go index 0ef58bf48..a25e3f4df 100644 --- a/x/evm/client/cli/tx.go +++ b/x/evm/client/cli/tx.go @@ -68,8 +68,10 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(NewAddERCNativePointerProposalTxCmd()) cmd.AddCommand(NewAddERCCW20PointerProposalTxCmd()) cmd.AddCommand(NewAddERCCW721PointerProposalTxCmd()) + cmd.AddCommand(NewAddERCCW1155PointerProposalTxCmd()) cmd.AddCommand(NewAddCWERC20PointerProposalTxCmd()) cmd.AddCommand(NewAddCWERC721PointerProposalTxCmd()) + cmd.AddCommand(NewAddCWERC1155PointerProposalTxCmd()) cmd.AddCommand(AssociateContractAddressCmd()) return cmd diff --git a/x/evm/gov.go b/x/evm/gov.go index 7d9229477..0a99b308a 100644 --- a/x/evm/gov.go +++ b/x/evm/gov.go @@ -45,6 +45,18 @@ func HandleAddERCCW721PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *type return k.SetERC721CW721PointerWithVersion(ctx, p.Pointee, common.HexToAddress(p.Pointer), uint16(p.Version)) } +func HandleAddERCCW1155PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddERCCW1155PointerProposal) error { + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "cw1155"), + sdk.NewAttribute(types.AttributeKeyPointerAddress, p.Pointer), sdk.NewAttribute(types.AttributeKeyPointee, p.Pointee), + sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", p.Version)))) + if p.Pointer == "" { + k.DeleteERC1155CW1155Pointer(ctx, p.Pointee, uint16(p.Version)) + return nil + } + return k.SetERC1155CW1155PointerWithVersion(ctx, p.Pointee, common.HexToAddress(p.Pointer), uint16(p.Version)) +} + func HandleAddCWERC20PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddCWERC20PointerProposal) error { ctx.EventManager().EmitEvent(sdk.NewEvent( types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "erc20"), @@ -68,3 +80,15 @@ func HandleAddCWERC721PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *type } return k.SetCW721ERC721PointerWithVersion(ctx, common.HexToAddress(p.Pointee), p.Pointer, uint16(p.Version)) } + +func HandleAddCWERC1155PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddCWERC1155PointerProposal) error { + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "erc1155"), + sdk.NewAttribute(types.AttributeKeyPointerAddress, p.Pointer), sdk.NewAttribute(types.AttributeKeyPointee, p.Pointee), + sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", p.Version)))) + if p.Pointer == "" { + k.DeleteCW1155ERC1155Pointer(ctx, common.HexToAddress(p.Pointee), uint16(p.Version)) + return nil + } + return k.SetCW1155ERC1155PointerWithVersion(ctx, common.HexToAddress(p.Pointee), p.Pointer, uint16(p.Version)) +} diff --git a/x/evm/gov_test.go b/x/evm/gov_test.go index 70ab53517..f36a20ee1 100644 --- a/x/evm/gov_test.go +++ b/x/evm/gov_test.go @@ -105,6 +105,38 @@ func TestAddERCCW721PointerProposals(t *testing.T) { require.Equal(t, addr, pointer1) } +func TestAddERCCW1155PointerProposals(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + _, pointer1 := testkeeper.MockAddressPair() + _, pointer2 := testkeeper.MockAddressPair() + require.Nil(t, evm.HandleAddERCCW1155PointerProposal(ctx, k, &types.AddERCCW1155PointerProposal{ + Pointee: "test", + Version: 1, + Pointer: pointer1.Hex(), + })) + addr, ver, exists := k.GetERC1155CW1155Pointer(ctx, "test") + require.True(t, exists) + require.Equal(t, uint16(1), ver) + require.Equal(t, addr, pointer1) + require.Nil(t, evm.HandleAddERCCW1155PointerProposal(ctx, k, &types.AddERCCW1155PointerProposal{ + Pointee: "test", + Version: 2, + Pointer: pointer2.Hex(), + })) + addr, ver, exists = k.GetERC1155CW1155Pointer(ctx, "test") + require.True(t, exists) + require.Equal(t, uint16(2), ver) + require.Equal(t, addr, pointer2) + require.Nil(t, evm.HandleAddERCCW1155PointerProposal(ctx, k, &types.AddERCCW1155PointerProposal{ + Pointee: "test", + Version: 2, + })) + addr, ver, exists = k.GetERC1155CW1155Pointer(ctx, "test") + require.True(t, exists) + require.Equal(t, uint16(1), ver) + require.Equal(t, addr, pointer1) +} + func TestAddCWERC20PointerProposals(t *testing.T) { k, ctx := testkeeper.MockEVMKeeper() _, pointee1 := testkeeper.MockAddressPair() @@ -170,3 +202,36 @@ func TestAddCWERC721PointerProposals(t *testing.T) { require.Equal(t, uint16(1), ver) require.Equal(t, addr, pointer1) } + +func TestAddCWERC1155PointerProposals(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + _, pointee1 := testkeeper.MockAddressPair() + pointer1, _ := testkeeper.MockAddressPair() + pointer2, _ := testkeeper.MockAddressPair() + require.Nil(t, evm.HandleAddCWERC1155PointerProposal(ctx, k, &types.AddCWERC1155PointerProposal{ + Pointee: pointee1.Hex(), + Version: 1, + Pointer: pointer1.String(), + })) + addr, ver, exists := k.GetCW1155ERC1155Pointer(ctx, pointee1) + require.True(t, exists) + require.Equal(t, uint16(1), ver) + require.Equal(t, addr, pointer1) + require.Nil(t, evm.HandleAddCWERC1155PointerProposal(ctx, k, &types.AddCWERC1155PointerProposal{ + Pointee: pointee1.Hex(), + Version: 2, + Pointer: pointer2.String(), + })) + addr, ver, exists = k.GetCW1155ERC1155Pointer(ctx, pointee1) + require.True(t, exists) + require.Equal(t, uint16(2), ver) + require.Equal(t, addr, pointer2) + require.Nil(t, evm.HandleAddCWERC1155PointerProposal(ctx, k, &types.AddCWERC1155PointerProposal{ + Pointee: pointee1.Hex(), + Version: 2, + })) + addr, ver, exists = k.GetCW1155ERC1155Pointer(ctx, pointee1) + require.True(t, exists) + require.Equal(t, uint16(1), ver) + require.Equal(t, addr, pointer1) +} diff --git a/x/evm/handler.go b/x/evm/handler.go index d75417883..9385a29c8 100644 --- a/x/evm/handler.go +++ b/x/evm/handler.go @@ -46,10 +46,14 @@ func NewProposalHandler(k keeper.Keeper) govtypes.Handler { return HandleAddERCCW20PointerProposal(ctx, &k, c) case *types.AddERCCW721PointerProposal: return HandleAddERCCW721PointerProposal(ctx, &k, c) + case *types.AddERCCW1155PointerProposal: + return HandleAddERCCW1155PointerProposal(ctx, &k, c) case *types.AddCWERC20PointerProposal: return HandleAddCWERC20PointerProposal(ctx, &k, c) case *types.AddCWERC721PointerProposal: return HandleAddCWERC721PointerProposal(ctx, &k, c) + case *types.AddCWERC1155PointerProposal: + return HandleAddCWERC1155PointerProposal(ctx, &k, c) default: return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized evm proposal content type: %T", c) } diff --git a/x/evm/keeper/genesis.go b/x/evm/keeper/genesis.go index a1a8606fc..94ceb4007 100644 --- a/x/evm/keeper/genesis.go +++ b/x/evm/keeper/genesis.go @@ -16,6 +16,7 @@ import ( "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" artifactsutils "github.com/sei-protocol/sei-chain/x/evm/artifacts/utils" "github.com/sei-protocol/sei-chain/x/evm/types" ) @@ -53,6 +54,15 @@ func (k *Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { artifactsutils.GetCodeIDBz(erc721CodeID), ) + erc1155CodeID, err := k.wasmKeeper.Create(ctx, k.accountKeeper.GetModuleAddress(types.ModuleName), erc1155.GetBin(), nil) + if err != nil { + panic(err) + } + prefix.NewStore(k.PrefixStore(ctx, types.PointerCWCodePrefix), types.PointerCW1155ERC1155Prefix).Set( + artifactsutils.GetVersionBz(erc1155.CurrentVersion), + artifactsutils.GetCodeIDBz(erc1155CodeID), + ) + if k.EthReplayConfig.Enabled && !ethReplayInitialied { header := k.OpenEthDatabase() k.SetReplayInitialHeight(ctx, header.Number.Int64()) diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 095f2c3c1..5df6e0a0e 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -9,8 +9,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/sei-protocol/sei-chain/x/evm/types" ) @@ -98,6 +100,13 @@ func (q Querier) Pointer(c context.Context, req *types.QueryPointerRequest) (*ty Version: uint32(v), Exists: e, }, nil + case types.PointerType_CW1155: + p, v, e := q.Keeper.GetERC1155CW1155Pointer(ctx, req.Pointee) + return &types.QueryPointerResponse{ + Pointer: p.Hex(), + Version: uint32(v), + Exists: e, + }, nil case types.PointerType_ERC20: p, v, e := q.Keeper.GetCW20ERC20Pointer(ctx, common.HexToAddress(req.Pointee)) return &types.QueryPointerResponse{ @@ -112,6 +121,13 @@ func (q Querier) Pointer(c context.Context, req *types.QueryPointerRequest) (*ty Version: uint32(v), Exists: e, }, nil + case types.PointerType_ERC1155: + p, v, e := q.Keeper.GetCW1155ERC1155Pointer(ctx, common.HexToAddress(req.Pointee)) + return &types.QueryPointerResponse{ + Pointer: p.String(), + Version: uint32(v), + Exists: e, + }, nil default: return nil, errors.ErrUnsupported } @@ -132,6 +148,10 @@ func (q Querier) PointerVersion(c context.Context, req *types.QueryPointerVersio return &types.QueryPointerVersionResponse{ Version: uint32(cw721.CurrentVersion), }, nil + case types.PointerType_CW1155: + return &types.QueryPointerVersionResponse{ + Version: uint32(cw1155.CurrentVersion), + }, nil case types.PointerType_ERC20: return &types.QueryPointerVersionResponse{ Version: uint32(erc20.CurrentVersion), @@ -142,6 +162,11 @@ func (q Querier) PointerVersion(c context.Context, req *types.QueryPointerVersio Version: uint32(erc721.CurrentVersion), CwCodeId: q.GetStoredPointerCodeID(ctx, types.PointerType_ERC721), }, nil + case types.PointerType_ERC1155: + return &types.QueryPointerVersionResponse{ + Version: uint32(erc1155.CurrentVersion), + CwCodeId: q.GetStoredPointerCodeID(ctx, types.PointerType_ERC1155), + }, nil default: return nil, errors.ErrUnsupported } diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index 30c26af00..94a9318a8 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -7,8 +7,10 @@ import ( testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -22,12 +24,16 @@ func TestQueryPointer(t *testing.T) { seiAddr3, evmAddr3 := testkeeper.MockAddressPair() seiAddr4, evmAddr4 := testkeeper.MockAddressPair() seiAddr5, evmAddr5 := testkeeper.MockAddressPair() + seiAddr6, evmAddr6 := testkeeper.MockAddressPair() + seiAddr7, evmAddr7 := testkeeper.MockAddressPair() goCtx := sdk.WrapSDKContext(ctx) k.SetERC20NativePointer(ctx, seiAddr1.String(), evmAddr1) k.SetERC20CW20Pointer(ctx, seiAddr2.String(), evmAddr2) k.SetERC721CW721Pointer(ctx, seiAddr3.String(), evmAddr3) k.SetCW20ERC20Pointer(ctx, evmAddr4, seiAddr4.String()) k.SetCW721ERC721Pointer(ctx, evmAddr5, seiAddr5.String()) + k.SetERC1155CW1155Pointer(ctx, seiAddr6.String(), evmAddr6) + k.SetCW1155ERC1155Pointer(ctx, evmAddr7, seiAddr7.String()) q := keeper.Querier{k} res, err := q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_NATIVE, Pointee: seiAddr1.String()}) require.Nil(t, err) @@ -44,4 +50,10 @@ func TestQueryPointer(t *testing.T) { res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_ERC721, Pointee: evmAddr5.Hex()}) require.Nil(t, err) require.Equal(t, types.QueryPointerResponse{Pointer: seiAddr5.String(), Version: uint32(erc721.CurrentVersion), Exists: true}, *res) + res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_CW1155, Pointee: seiAddr3.String()}) + require.Nil(t, err) + require.Equal(t, types.QueryPointerResponse{Pointer: evmAddr3.Hex(), Version: uint32(cw1155.CurrentVersion), Exists: true}, *res) + res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_ERC1155, Pointee: evmAddr5.Hex()}) + require.Nil(t, err) + require.Equal(t, types.QueryPointerResponse{Pointer: seiAddr5.String(), Version: uint32(erc1155.CurrentVersion), Exists: true}, *res) } diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 9ccb8779a..ef4b509f8 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -23,6 +23,7 @@ import ( "github.com/sei-protocol/sei-chain/utils" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" ) @@ -281,6 +282,9 @@ func (server msgServer) RegisterPointer(goCtx context.Context, msg *types.MsgReg case types.PointerType_ERC721: currentVersion = erc721.CurrentVersion existingPointer, existingVersion, exists = server.GetCW721ERC721Pointer(ctx, common.HexToAddress(msg.ErcAddress)) + case types.PointerType_ERC1155: + currentVersion = erc1155.CurrentVersion + existingPointer, existingVersion, exists = server.GetCW1155ERC1155Pointer(ctx, common.HexToAddress(msg.ErcAddress)) default: panic("unknown pointer type") } @@ -293,6 +297,8 @@ func (server msgServer) RegisterPointer(goCtx context.Context, msg *types.MsgReg payload["erc20_address"] = msg.ErcAddress case types.PointerType_ERC721: payload["erc721_address"] = msg.ErcAddress + case types.PointerType_ERC1155: + payload["erc1155_address"] = msg.ErcAddress default: panic("unknown pointer type") } @@ -319,6 +325,12 @@ func (server msgServer) RegisterPointer(goCtx context.Context, msg *types.MsgReg types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "erc721"), sdk.NewAttribute(types.AttributeKeyPointerAddress, pointerAddr.String()), sdk.NewAttribute(types.AttributeKeyPointee, msg.ErcAddress), sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", erc721.CurrentVersion)))) + case types.PointerType_ERC1155: + err = server.SetCW1155ERC1155Pointer(ctx, common.HexToAddress(msg.ErcAddress), pointerAddr.String()) + ctx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "erc1155"), + sdk.NewAttribute(types.AttributeKeyPointerAddress, pointerAddr.String()), sdk.NewAttribute(types.AttributeKeyPointee, msg.ErcAddress), + sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", erc1155.CurrentVersion)))) default: panic("unknown pointer type") } diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index 3ca811cfb..07173e070 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -21,6 +21,7 @@ import ( "github.com/sei-protocol/sei-chain/x/evm/ante" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -514,6 +515,8 @@ func TestRegisterPointer(t *testing.T) { k, ctx := testkeeper.MockEVMKeeper() sender, _ := testkeeper.MockAddressPair() _, pointee := testkeeper.MockAddressPair() + + // Test register-pointer for ERC20 res, err := keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ Sender: sender.String(), PointerType: types.PointerType_ERC20, @@ -536,7 +539,7 @@ func TestRegisterPointer(t *testing.T) { require.True(t, hasRegisteredEvent) ctx = ctx.WithEventManager(sdk.NewEventManager()) - // already exists + // ERC20 pointer already exists _, err = keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ Sender: sender.String(), PointerType: types.PointerType_ERC20, @@ -553,6 +556,7 @@ func TestRegisterPointer(t *testing.T) { require.False(t, hasRegisteredEvent) ctx = ctx.WithEventManager(sdk.NewEventManager()) + // Test register-pointer for ERC721 res, err = keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ Sender: sender.String(), PointerType: types.PointerType_ERC721, @@ -575,7 +579,7 @@ func TestRegisterPointer(t *testing.T) { require.True(t, hasRegisteredEvent) ctx = ctx.WithEventManager(sdk.NewEventManager()) - // already exists + // ERC721 pointer already exists _, err = keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ Sender: sender.String(), PointerType: types.PointerType_ERC721, @@ -590,6 +594,46 @@ func TestRegisterPointer(t *testing.T) { hasRegisteredEvent = true } require.False(t, hasRegisteredEvent) + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + // Test register-pointer for ERC1155 + res, err = keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ + Sender: sender.String(), + PointerType: types.PointerType_ERC1155, + ErcAddress: pointee.Hex(), + }) + require.Nil(t, err) + pointer, version, exists = k.GetCW1155ERC1155Pointer(ctx, pointee) + require.True(t, exists) + require.Equal(t, erc1155.CurrentVersion, version) + require.Equal(t, pointer.String(), res.PointerAddress) + hasRegisteredEvent = false + for _, e := range ctx.EventManager().Events() { + if e.Type != types.EventTypePointerRegistered { + continue + } + hasRegisteredEvent = true + require.Equal(t, types.EventTypePointerRegistered, e.Type) + require.Equal(t, "erc1155", string(e.Attributes[0].Value)) + } + require.True(t, hasRegisteredEvent) + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + // ERC1155 pointer already exists + _, err = keeper.NewMsgServerImpl(k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ + Sender: sender.String(), + PointerType: types.PointerType_ERC1155, + ErcAddress: pointee.Hex(), + }) + require.NotNil(t, err) + hasRegisteredEvent = false + for _, e := range ctx.EventManager().Events() { + if e.Type != types.EventTypePointerRegistered { + continue + } + hasRegisteredEvent = true + } + require.False(t, hasRegisteredEvent) } func TestEvmError(t *testing.T) { diff --git a/x/evm/keeper/pointer.go b/x/evm/keeper/pointer.go index 33e1a6fed..76a28a178 100644 --- a/x/evm/keeper/pointer.go +++ b/x/evm/keeper/pointer.go @@ -11,8 +11,10 @@ import ( "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" artifactsutils "github.com/sei-protocol/sei-chain/x/evm/artifacts/utils" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -125,6 +127,41 @@ func (k *Keeper) DeleteERC721CW721Pointer(ctx sdk.Context, cw721Address string, } } +// ERC1155 -> CW1155 +func (k *Keeper) SetERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string, addr common.Address) error { + return k.SetERC1155CW1155PointerWithVersion(ctx, 1155Address, addr, 1155.CurrentVersion) +} + +// ERC1155 -> CW1155 +func (k *Keeper) SetERC1155CW1155PointerWithVersion(ctx sdk.Context, cw1155Address string, addr common.Address, version uint16) error { + if k.cwAddressIsPointer(ctx, cw1155Address) { + return ErrorPointerToPointerNotAllowed + } + err := k.setPointerInfo(ctx, types.PointerERC1155CW1155Key(cw1155Address), addr[:], version) + if err != nil { + return err + } + return k.setPointerInfo(ctx, types.PointerReverseRegistryKey(addr), []byte(cw1155Address), version) +} + +// ERC1155 -> CW1155 +func (k *Keeper) GetERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string) (addr common.Address, version uint16, exists bool) { + addrBz, version, exists := k.GetPointerInfo(ctx, types.PointerERC1155CW1155Key(cw1155Address)) + if exists { + addr = common.BytesToAddress(addrBz) + } + return +} + +// ERC1155 -> CW1155 +func (k *Keeper) DeleteERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string, version uint16) { + addr, _, exists := k.GetERC1155CW1155Pointer(ctx, cw1155Address) + if exists { + k.deletePointerInfo(ctx, types.PointerERC1155CW1155Key(cw1155Address), version) + k.deletePointerInfo(ctx, types.PointerReverseRegistryKey(addr), version) + } +} + // CW20 -> ERC20 func (k *Keeper) SetCW20ERC20Pointer(ctx sdk.Context, erc20Address common.Address, addr string) error { return k.SetCW20ERC20PointerWithVersion(ctx, erc20Address, addr, erc20.CurrentVersion) @@ -205,6 +242,41 @@ func (k *Keeper) DeleteCW721ERC721Pointer(ctx sdk.Context, erc721Address common. } } +// CW1155 -> ERC1155 +func (k *Keeper) SetCW1155ERC1155Pointer(ctx sdk.Context, erc1155Address common.Address, addr string) error { + return k.SetCW1155ERC1155PointerWithVersion(ctx, erc1155Address, addr, erc1155.CurrentVersion) +} + +// CW1155 -> ERC1155 +func (k *Keeper) SetCW1155ERC1155PointerWithVersion(ctx sdk.Context, erc1155Address common.Address, addr string, version uint16) error { + if k.evmAddressIsPointer(ctx, erc1155Address) { + return ErrorPointerToPointerNotAllowed + } + err := k.setPointerInfo(ctx, types.PointerCW1155ERC1155Key(erc1155Address), []byte(addr), version) + if err != nil { + return err + } + return k.setPointerInfo(ctx, types.PointerReverseRegistryKey(common.BytesToAddress([]byte(addr))), erc1155Address[:], version) +} + +// CW1155 -> ERC1155 +func (k *Keeper) GetCW1155ERC1155Pointer(ctx sdk.Context, erc1155Address common.Address) (addr sdk.AccAddress, version uint16, exists bool) { + addrBz, version, exists := k.GetPointerInfo(ctx, types.PointerCW1155ERC1155Key(erc1155Address)) + if exists { + addr = sdk.MustAccAddressFromBech32(string(addrBz)) + } + return +} + +// CW1155 -> ERC1155 +func (k *Keeper) DeleteCW1155ERC1155Pointer(ctx sdk.Context, erc1155Address common.Address, version uint16) { + addr, _, exists := k.GetCW1155ERC1155Pointer(ctx, erc1155Address) + if exists { + k.deletePointerInfo(ctx, types.PointerCW1155ERC1155Key(erc1155Address), version) + k.deletePointerInfo(ctx, types.PointerReverseRegistryKey(common.BytesToAddress([]byte(addr.String()))), version) + } +} + func (k *Keeper) GetPointerInfo(ctx sdk.Context, pref []byte) (addr []byte, version uint16, exists bool) { store := prefix.NewStore(ctx.KVStore(k.GetStoreKey()), pref) iter := store.ReverseIterator(nil, nil) @@ -247,6 +319,9 @@ func (k *Keeper) GetStoredPointerCodeID(ctx sdk.Context, pointerType types.Point case types.PointerType_ERC721: store = prefix.NewStore(store, types.PointerCW721ERC721Prefix) versionBz = artifactsutils.GetVersionBz(erc721.CurrentVersion) + case types.PointerType_ERC1155: + store = prefix.NewStore(store, types.PointerCW1155ERC1155Prefix) + versionBz = artifactsutils.GetVersionBz(erc1155.CurrentVersion) default: return 0 } diff --git a/x/evm/keeper/pointer_test.go b/x/evm/keeper/pointer_test.go index 3563ebeeb..0f99d6976 100644 --- a/x/evm/keeper/pointer_test.go +++ b/x/evm/keeper/pointer_test.go @@ -10,6 +10,7 @@ import ( testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper" ) @@ -60,6 +61,19 @@ func TestEVMtoCWPointers(t *testing.T) { }, version: native.CurrentVersion, }, + { + name: "ERC20NativePointer prevents pointer to cw1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC20NativePointer, + evmGetter: k.GetERC20NativePointer, + evmDeleter: k.DeleteERC20NativePointer, + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + } + }, + version: native.CurrentVersion, + }, { name: "ERC20CW20Pointer prevents pointer to cw721 pointer", getHandlers: func(k *evmkeeper.Keeper) *handlers { @@ -73,6 +87,19 @@ func TestEVMtoCWPointers(t *testing.T) { }, version: cw20.CurrentVersion(ctx), }, + { + name: "ERC20CW20Pointer prevents pointer to cw1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC20CW20Pointer, + evmGetter: k.GetERC20CW20Pointer, + evmDeleter: k.DeleteERC20CW20Pointer, + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + } + }, + version: cw20.CurrentVersion(ctx), + }, { name: "ERC20CW20Pointer prevents pointer to cw20 pointer", getHandlers: func(k *evmkeeper.Keeper) *handlers { @@ -99,6 +126,19 @@ func TestEVMtoCWPointers(t *testing.T) { }, version: cw721.CurrentVersion, }, + { + name: "ERC721CW721Pointer prevents pointer to cw1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC721CW721Pointer, + evmGetter: k.GetERC721CW721Pointer, + evmDeleter: k.DeleteERC721CW721Pointer, + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + } + }, + version: cw721.CurrentVersion, + }, { name: "ERC721CW721Pointer prevents pointer to cw20 pointer", getHandlers: func(k *evmkeeper.Keeper) *handlers { @@ -112,6 +152,45 @@ func TestEVMtoCWPointers(t *testing.T) { }, version: cw721.CurrentVersion, }, + { + name: "ERC1155CW1155Pointer prevents pointer to cw721 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + evmDeleter: k.DeleteERC1155CW1155Pointer, + cwSetter: k.SetCW721ERC721Pointer, + cwGetter: k.GetCW721ERC721Pointer, + } + }, + version: cw1155.CurrentVersion, + }, + { + name: "ERC1155CW1155Pointer prevents pointer to cw1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + evmDeleter: k.DeleteERC1155CW1155Pointer, + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + } + }, + version: cw1155.CurrentVersion, + }, + { + name: "ERC1155CW1155Pointer prevents pointer to cw20 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + evmDeleter: k.DeleteERC1155CW1155Pointer, + cwSetter: k.SetCW20ERC20Pointer, + cwGetter: k.GetCW20ERC20Pointer, + } + }, + version: cw1155.CurrentVersion, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -184,6 +263,17 @@ func TestCWtoEVMPointers(t *testing.T) { } }, }, + { + name: "CW20ERC20Pointer prevents pointer to erc1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW20ERC20Pointer, + cwGetter: k.GetCW20ERC20Pointer, + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + } + }, + }, { name: "CW721ERC721Pointer prevents pointer to native pointer", getHandlers: func(k *evmkeeper.Keeper) *handlers { @@ -217,6 +307,61 @@ func TestCWtoEVMPointers(t *testing.T) { } }, }, + { + name: "CW721ERC721Pointer prevents pointer to erc1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW721ERC721Pointer, + cwGetter: k.GetCW721ERC721Pointer, + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + } + }, + }, + { + name: "CW1155ERC1155Pointer prevents pointer to native pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + evmSetter: k.SetERC20NativePointer, + evmGetter: k.GetERC20NativePointer, + } + }, + }, + { + name: "CW1155ERC1155Pointer prevents pointer to erc721 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + evmSetter: k.SetERC721CW721Pointer, + evmGetter: k.GetERC721CW721Pointer, + } + }, + }, + { + name: "CW1155ERC1155Pointer prevents pointer to erc20 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + evmSetter: k.SetERC20CW20Pointer, + evmGetter: k.GetERC20CW20Pointer, + } + }, + }, + { + name: "CW1155ERC1155Pointer prevents pointer to erc1155 pointer", + getHandlers: func(k *evmkeeper.Keeper) *handlers { + return &handlers{ + cwSetter: k.SetCW1155ERC1155Pointer, + cwGetter: k.GetCW1155ERC1155Pointer, + evmSetter: k.SetERC1155CW1155Pointer, + evmGetter: k.GetERC1155CW1155Pointer, + } + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/x/evm/migrations/store_cw_pointer_code.go b/x/evm/migrations/store_cw_pointer_code.go index 3dea8ed44..11a092dc6 100644 --- a/x/evm/migrations/store_cw_pointer_code.go +++ b/x/evm/migrations/store_cw_pointer_code.go @@ -5,12 +5,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20" "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/erc1155" artifactsutils "github.com/sei-protocol/sei-chain/x/evm/artifacts/utils" "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/types" ) -func StoreCWPointerCode(ctx sdk.Context, k *keeper.Keeper, store20 bool, store721 bool) error { +func StoreCWPointerCode(ctx sdk.Context, k *keeper.Keeper, store20 bool, store721 bool, store1155 bool) error { if store20 { erc20CodeID, err := k.WasmKeeper().Create(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), erc20.GetBin(), nil) if err != nil { @@ -32,5 +33,16 @@ func StoreCWPointerCode(ctx sdk.Context, k *keeper.Keeper, store20 bool, store72 artifactsutils.GetCodeIDBz(erc721CodeID), ) } + + if store1155 { + erc1155CodeID, err := k.WasmKeeper().Create(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), erc1155.GetBin(), nil) + if err != nil { + panic(err) + } + prefix.NewStore(k.PrefixStore(ctx, types.PointerCWCodePrefix), types.PointerCW1155ERC1155Prefix).Set( + artifactsutils.GetVersionBz(erc1155.CurrentVersion), + artifactsutils.GetCodeIDBz(erc1155CodeID), + ) + } return nil } diff --git a/x/evm/module.go b/x/evm/module.go index ac787ca5b..6ce15a967 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -141,7 +141,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { }) _ = cfg.RegisterMigration(types.ModuleName, 4, func(ctx sdk.Context) error { - return migrations.StoreCWPointerCode(ctx, am.keeper, true, true) + return migrations.StoreCWPointerCode(ctx, am.keeper, true, true, false) }) _ = cfg.RegisterMigration(types.ModuleName, 5, func(ctx sdk.Context) error { @@ -149,11 +149,11 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { }) _ = cfg.RegisterMigration(types.ModuleName, 6, func(ctx sdk.Context) error { - return migrations.StoreCWPointerCode(ctx, am.keeper, false, true) + return migrations.StoreCWPointerCode(ctx, am.keeper, false, true, false) }) _ = cfg.RegisterMigration(types.ModuleName, 7, func(ctx sdk.Context) error { - return migrations.StoreCWPointerCode(ctx, am.keeper, false, true) + return migrations.StoreCWPointerCode(ctx, am.keeper, false, true, false) }) } diff --git a/x/evm/types/codec.go b/x/evm/types/codec.go index 890b208ed..4f644da62 100644 --- a/x/evm/types/codec.go +++ b/x/evm/types/codec.go @@ -36,8 +36,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { &AddERCNativePointerProposal{}, &AddERCCW20PointerProposal{}, &AddERCCW721PointerProposal{}, + &AddERCCW1155PointerProposal{}, &AddCWERC20PointerProposal{}, &AddCWERC721PointerProposal{}, + &AddCWERC1155PointerProposal{}, ) registry.RegisterImplementations( (*sdk.Msg)(nil), diff --git a/x/evm/types/enums.pb.go b/x/evm/types/enums.pb.go index d5f2e5642..083a9466d 100644 --- a/x/evm/types/enums.pb.go +++ b/x/evm/types/enums.pb.go @@ -23,11 +23,13 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type PointerType int32 const ( - PointerType_ERC20 PointerType = 0 - PointerType_ERC721 PointerType = 1 - PointerType_NATIVE PointerType = 2 - PointerType_CW20 PointerType = 3 - PointerType_CW721 PointerType = 4 + PointerType_ERC20 PointerType = 0 + PointerType_ERC721 PointerType = 1 + PointerType_NATIVE PointerType = 2 + PointerType_CW20 PointerType = 3 + PointerType_CW721 PointerType = 4 + PointerType_ERC1155 PointerType = 5 + PointerType_CW1155 PointerType = 6 ) var PointerType_name = map[int32]string{ @@ -36,14 +38,18 @@ var PointerType_name = map[int32]string{ 2: "NATIVE", 3: "CW20", 4: "CW721", + 5: "ERC1155", + 6: "CW1155", } var PointerType_value = map[string]int32{ - "ERC20": 0, - "ERC721": 1, - "NATIVE": 2, - "CW20": 3, - "CW721": 4, + "ERC20": 0, + "ERC721": 1, + "NATIVE": 2, + "CW20": 3, + "CW721": 4, + "ERC1155": 5, + "CW1155": 6, } func (x PointerType) String() string { diff --git a/x/evm/types/gov.go b/x/evm/types/gov.go index 13f35800c..270834533 100644 --- a/x/evm/types/gov.go +++ b/x/evm/types/gov.go @@ -15,8 +15,10 @@ const ( ProposalTypeAddERCNativePointer = "AddERCNativePointer" ProposalTypeAddERCCW20Pointer = "AddERCCW20Pointer" ProposalTypeAddERCCW721Pointer = "AddERCCW721Pointer" + ProposalTypeAddERCCW1155Pointer = "AddERCCW1155Pointer" ProposalTypeAddCWERC20Pointer = "AddCWERC20Pointer" ProposalTypeAddCWERC721Pointer = "AddCWERC721Pointer" + ProposalTypeAddCWERC1155Pointer = "AddCWERC1155Pointer" ) func init() { @@ -24,15 +26,19 @@ func init() { govtypes.RegisterProposalType(ProposalTypeAddERCNativePointer) govtypes.RegisterProposalType(ProposalTypeAddERCCW20Pointer) govtypes.RegisterProposalType(ProposalTypeAddERCCW721Pointer) + govtypes.RegisterProposalType(ProposalTypeAddERCCW1155Pointer) govtypes.RegisterProposalType(ProposalTypeAddCWERC20Pointer) govtypes.RegisterProposalType(ProposalTypeAddCWERC721Pointer) + govtypes.RegisterProposalType(ProposalTypeAddCWERC1155Pointer) // for marshal and unmarshal govtypes.RegisterProposalTypeCodec(&AddERCNativePointerProposal{}, "evm/AddERCNativePointerProposal") govtypes.RegisterProposalTypeCodec(&AddERCCW20PointerProposal{}, "evm/AddERCCW20PointerProposal") govtypes.RegisterProposalTypeCodec(&AddERCCW721PointerProposal{}, "evm/AddERCCW721PointerProposal") + govtypes.RegisterProposalTypeCodec(&AddERCCW1155PointerProposal{}, "evm/AddERCCW1155PointerProposal") govtypes.RegisterProposalTypeCodec(&AddCWERC20PointerProposal{}, "evm/AddCWERC20PointerProposal") govtypes.RegisterProposalTypeCodec(&AddCWERC721PointerProposal{}, "evm/AddCWERC721PointerProposal") + govtypes.RegisterProposalTypeCodec(&AddCWERC1155PointerProposal{}, "evm/AddCWERC1155PointerProposal") } func (p *AddERCNativePointerProposal) GetTitle() string { return p.Title } @@ -145,6 +151,44 @@ func (p AddERCCW721PointerProposal) String() string { return b.String() } +func (p *AddERCCW1155PointerProposal) GetTitle() string { return p.Title } + +func (p *AddERCCW1155PointerProposal) GetDescription() string { return p.Description } + +func (p *AddERCCW1155PointerProposal) ProposalRoute() string { return RouterKey } + +func (p *AddERCCW1155PointerProposal) ProposalType() string { + return ProposalTypeAddERCCW1155Pointer +} + +func (p *AddERCCW1155PointerProposal) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(p.Pointee); err != nil { + return err + } + + if p.Pointer != "" && !common.IsHexAddress(p.Pointer) { + return errors.New("pointer address must be either empty or a valid hex-encoded string") + } + + if p.Version > math.MaxUint16 { + return errors.New("pointer version must be <= 65535") + } + + return govtypes.ValidateAbstract(p) +} + +func (p AddERCCW1155PointerProposal) String() string { + var b strings.Builder + b.WriteString(fmt.Sprintf(`Add ERC CW1155 pointer Proposal: + Title: %s + Description: %s + Pointee: %s + Pointer: %s + Version: %d +`, p.Title, p.Description, p.Pointee, p.Pointer, p.Version)) + return b.String() +} + func (p *AddCWERC20PointerProposal) GetTitle() string { return p.Title } func (p *AddCWERC20PointerProposal) GetDescription() string { return p.Description } @@ -222,3 +266,42 @@ func (p AddCWERC721PointerProposal) String() string { `, p.Title, p.Description, p.Pointee, p.Pointer, p.Version)) return b.String() } + +func (p *AddCWERC1155PointerProposal) GetTitle() string { return p.Title } + +func (p *AddCWERC1155PointerProposal) GetDescription() string { return p.Description } + +func (p *AddCWERC1155PointerProposal) ProposalRoute() string { return RouterKey } + +func (p *AddCWERC1155PointerProposal) ProposalType() string { + return ProposalTypeAddCWERC1155Pointer +} + +func (p *AddCWERC1155PointerProposal) ValidateBasic() error { + if p.Pointer != "" { + if _, err := sdk.AccAddressFromBech32(p.Pointer); err != nil { + return err + } + } + if !common.IsHexAddress(p.Pointee) { + return errors.New("pointee address must be either empty or a valid hex-encoded string") + } + + if p.Version > math.MaxUint16 { + return errors.New("pointer version must be <= 65535") + } + + return govtypes.ValidateAbstract(p) +} + +func (p AddCWERC1155PointerProposal) String() string { + var b strings.Builder + b.WriteString(fmt.Sprintf(`Add CW ERC1155 pointer Proposal: + Title: %s + Description: %s + Pointee: %s + Pointer: %s + Version: %d +`, p.Title, p.Description, p.Pointee, p.Pointer, p.Version)) + return b.String() +} diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index 70bd37119..7ae0bad92 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -54,11 +54,13 @@ var ( ) var ( - PointerERC20NativePrefix = []byte{0x0} - PointerERC20CW20Prefix = []byte{0x1} - PointerERC721CW721Prefix = []byte{0x2} - PointerCW20ERC20Prefix = []byte{0x3} - PointerCW721ERC721Prefix = []byte{0x4} + PointerERC20NativePrefix = []byte{0x0} + PointerERC20CW20Prefix = []byte{0x1} + PointerERC721CW721Prefix = []byte{0x2} + PointerCW20ERC20Prefix = []byte{0x3} + PointerCW721ERC721Prefix = []byte{0x4} + PointerERC1155CW1155Prefix = []byte{0x5} + PointerCW1155ERC1155Prefix = []byte{0x6} ) func EVMAddressToSeiAddressKey(evmAddress common.Address) []byte { @@ -110,6 +112,13 @@ func PointerERC721CW721Key(cw721Address string) []byte { ) } +func PointerERC1155CW1155Key(cw1155Address string) []byte { + return append( + append(PointerRegistryPrefix, PointerERC1155CW1155Prefix...), + []byte(cw1155Address)..., + ) +} + func PointerCW20ERC20Key(erc20Addr common.Address) []byte { return append( append(PointerRegistryPrefix, PointerCW20ERC20Prefix...), @@ -124,6 +133,13 @@ func PointerCW721ERC721Key(erc721Addr common.Address) []byte { ) } +func PointerCW1155ERC1155Key(erc1155Addr common.Address) []byte { + return append( + append(PointerRegistryPrefix, PointerCW1155ERC1155Prefix...), + erc1155Addr[:]..., + ) +} + func PointerReverseRegistryKey(addr common.Address) []byte { return append(PointerReverseRegistryPrefix, addr[:]...) } diff --git a/x/evm/types/message_register_pointer.go b/x/evm/types/message_register_pointer.go index 831f1a0ae..84fb7331f 100644 --- a/x/evm/types/message_register_pointer.go +++ b/x/evm/types/message_register_pointer.go @@ -20,6 +20,10 @@ func NewMsgRegisterERC721Pointer(sender sdk.AccAddress, ercAddress common.Addres return &MsgRegisterPointer{Sender: sender.String(), ErcAddress: ercAddress.Hex(), PointerType: PointerType_ERC721} } +func NewMsgRegisterERC1155Pointer(sender sdk.AccAddress, ercAddress common.Address) *MsgRegisterPointer { + return &MsgRegisterPointer{Sender: sender.String(), ErcAddress: ercAddress.Hex(), PointerType: PointerType_ERC1155} +} + func (msg *MsgRegisterPointer) Route() string { return RouterKey } From 3502209aea560bafa7f40b1cf40b9a5771bd1cd7 Mon Sep 17 00:00:00 2001 From: davyli Date: Fri, 21 Jun 2024 08:58:16 -0400 Subject: [PATCH 12/65] Fix typo --- x/evm/keeper/pointer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/evm/keeper/pointer.go b/x/evm/keeper/pointer.go index 76a28a178..48aa45009 100644 --- a/x/evm/keeper/pointer.go +++ b/x/evm/keeper/pointer.go @@ -129,7 +129,7 @@ func (k *Keeper) DeleteERC721CW721Pointer(ctx sdk.Context, cw721Address string, // ERC1155 -> CW1155 func (k *Keeper) SetERC1155CW1155Pointer(ctx sdk.Context, cw1155Address string, addr common.Address) error { - return k.SetERC1155CW1155PointerWithVersion(ctx, 1155Address, addr, 1155.CurrentVersion) + return k.SetERC1155CW1155PointerWithVersion(ctx, cw1155Address, addr, cw1155.CurrentVersion) } // ERC1155 -> CW1155 From cca521c7dbddf7a004492f6936058d1d1f1c068f Mon Sep 17 00:00:00 2001 From: davyli Date: Fri, 21 Jun 2024 08:58:30 -0400 Subject: [PATCH 13/65] Add updated protobuf files --- x/evm/types/enums.pb.go | 17 +- x/evm/types/gov.pb.go | 677 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 670 insertions(+), 24 deletions(-) diff --git a/x/evm/types/enums.pb.go b/x/evm/types/enums.pb.go index 083a9466d..616cc6a9c 100644 --- a/x/evm/types/enums.pb.go +++ b/x/evm/types/enums.pb.go @@ -67,18 +67,19 @@ func init() { func init() { proto.RegisterFile("evm/enums.proto", fileDescriptor_9ba0923a26222f98) } var fileDescriptor_9ba0923a26222f98 = []byte{ - // 194 bytes of a gzipped FileDescriptorProto + // 214 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0x2d, 0xcb, 0xd5, 0x4f, 0xcd, 0x2b, 0xcd, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x28, 0x4e, 0xcd, 0x04, 0xb3, 0x92, 0xf3, 0x73, 0xf4, 0x8a, 0x53, 0x33, 0x93, 0x33, 0x12, 0x33, 0xf3, 0xf4, 0x52, - 0xcb, 0x72, 0xb5, 0x5c, 0xb9, 0xb8, 0x03, 0xf2, 0x33, 0xf3, 0x4a, 0x52, 0x8b, 0x42, 0x2a, 0x0b, + 0xcb, 0x72, 0xb5, 0xe2, 0xb8, 0xb8, 0x03, 0xf2, 0x33, 0xf3, 0x4a, 0x52, 0x8b, 0x42, 0x2a, 0x0b, 0x52, 0x85, 0x38, 0xb9, 0x58, 0x5d, 0x83, 0x9c, 0x8d, 0x0c, 0x04, 0x18, 0x84, 0xb8, 0xb8, 0xd8, 0x5c, 0x83, 0x9c, 0xcd, 0x8d, 0x0c, 0x05, 0x18, 0x41, 0x6c, 0x3f, 0xc7, 0x10, 0xcf, 0x30, 0x57, 0x01, 0x26, 0x21, 0x0e, 0x2e, 0x16, 0xe7, 0x70, 0x23, 0x03, 0x01, 0x66, 0x90, 0x62, 0xe7, 0x70, - 0x90, 0x02, 0x16, 0x27, 0xf7, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, - 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, - 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, 0x4e, 0xcd, 0xd4, 0x85, - 0x39, 0x03, 0xcc, 0x01, 0xbb, 0x43, 0xbf, 0x42, 0x1f, 0xe4, 0xde, 0x92, 0xca, 0x82, 0xd4, 0xe2, - 0x24, 0x36, 0xb0, 0xbc, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x3c, 0xe6, 0x84, 0x48, 0xc3, 0x00, - 0x00, 0x00, + 0x90, 0x02, 0x16, 0x21, 0x6e, 0x2e, 0x76, 0xd7, 0x20, 0x67, 0x43, 0x43, 0x53, 0x53, 0x01, 0x56, + 0x90, 0x6a, 0xe7, 0x70, 0x30, 0x9b, 0xcd, 0xc9, 0xfd, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, + 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, + 0xe5, 0x18, 0xa2, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x8b, + 0x53, 0x33, 0x75, 0x61, 0xee, 0x03, 0x73, 0xc0, 0x0e, 0xd4, 0xaf, 0xd0, 0x07, 0x79, 0xa4, 0xa4, + 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x2c, 0x6f, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x3a, + 0x55, 0xe4, 0xdc, 0x00, 0x00, 0x00, } diff --git a/x/evm/types/gov.pb.go b/x/evm/types/gov.pb.go index ef6f6457e..43da1b8bf 100644 --- a/x/evm/types/gov.pb.go +++ b/x/evm/types/gov.pb.go @@ -143,6 +143,46 @@ func (m *AddERCCW721PointerProposal) XXX_DiscardUnknown() { var xxx_messageInfo_AddERCCW721PointerProposal proto.InternalMessageInfo +type AddERCCW1155PointerProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Pointee string `protobuf:"bytes,3,opt,name=pointee,proto3" json:"pointee,omitempty" yaml:"pointee"` + Pointer string `protobuf:"bytes,4,opt,name=pointer,proto3" json:"pointer,omitempty" yaml:"pointer"` + Version uint32 `protobuf:"varint,5,opt,name=version,proto3" json:"version,omitempty" yaml:"version"` +} + +func (m *AddERCCW1155PointerProposal) Reset() { *m = AddERCCW1155PointerProposal{} } +func (*AddERCCW1155PointerProposal) ProtoMessage() {} +func (*AddERCCW1155PointerProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_fb66eb1aab5c39af, []int{3} +} +func (m *AddERCCW1155PointerProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AddERCCW1155PointerProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AddERCCW1155PointerProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AddERCCW1155PointerProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_AddERCCW1155PointerProposal.Merge(m, src) +} +func (m *AddERCCW1155PointerProposal) XXX_Size() int { + return m.Size() +} +func (m *AddERCCW1155PointerProposal) XXX_DiscardUnknown() { + xxx_messageInfo_AddERCCW1155PointerProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_AddERCCW1155PointerProposal proto.InternalMessageInfo + type AddCWERC20PointerProposal struct { Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` @@ -154,7 +194,7 @@ type AddCWERC20PointerProposal struct { func (m *AddCWERC20PointerProposal) Reset() { *m = AddCWERC20PointerProposal{} } func (*AddCWERC20PointerProposal) ProtoMessage() {} func (*AddCWERC20PointerProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_fb66eb1aab5c39af, []int{3} + return fileDescriptor_fb66eb1aab5c39af, []int{4} } func (m *AddCWERC20PointerProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -194,7 +234,7 @@ type AddCWERC721PointerProposal struct { func (m *AddCWERC721PointerProposal) Reset() { *m = AddCWERC721PointerProposal{} } func (*AddCWERC721PointerProposal) ProtoMessage() {} func (*AddCWERC721PointerProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_fb66eb1aab5c39af, []int{4} + return fileDescriptor_fb66eb1aab5c39af, []int{5} } func (m *AddCWERC721PointerProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -223,18 +263,60 @@ func (m *AddCWERC721PointerProposal) XXX_DiscardUnknown() { var xxx_messageInfo_AddCWERC721PointerProposal proto.InternalMessageInfo +type AddCWERC1155PointerProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` + Pointee string `protobuf:"bytes,3,opt,name=pointee,proto3" json:"pointee,omitempty" yaml:"pointee"` + Pointer string `protobuf:"bytes,4,opt,name=pointer,proto3" json:"pointer,omitempty" yaml:"pointer"` + Version uint32 `protobuf:"varint,5,opt,name=version,proto3" json:"version,omitempty" yaml:"version"` +} + +func (m *AddCWERC1155PointerProposal) Reset() { *m = AddCWERC1155PointerProposal{} } +func (*AddCWERC1155PointerProposal) ProtoMessage() {} +func (*AddCWERC1155PointerProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_fb66eb1aab5c39af, []int{6} +} +func (m *AddCWERC1155PointerProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AddCWERC1155PointerProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AddCWERC1155PointerProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AddCWERC1155PointerProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_AddCWERC1155PointerProposal.Merge(m, src) +} +func (m *AddCWERC1155PointerProposal) XXX_Size() int { + return m.Size() +} +func (m *AddCWERC1155PointerProposal) XXX_DiscardUnknown() { + xxx_messageInfo_AddCWERC1155PointerProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_AddCWERC1155PointerProposal proto.InternalMessageInfo + func init() { proto.RegisterType((*AddERCNativePointerProposal)(nil), "seiprotocol.seichain.evm.AddERCNativePointerProposal") proto.RegisterType((*AddERCCW20PointerProposal)(nil), "seiprotocol.seichain.evm.AddERCCW20PointerProposal") proto.RegisterType((*AddERCCW721PointerProposal)(nil), "seiprotocol.seichain.evm.AddERCCW721PointerProposal") + proto.RegisterType((*AddERCCW1155PointerProposal)(nil), "seiprotocol.seichain.evm.AddERCCW1155PointerProposal") proto.RegisterType((*AddCWERC20PointerProposal)(nil), "seiprotocol.seichain.evm.AddCWERC20PointerProposal") proto.RegisterType((*AddCWERC721PointerProposal)(nil), "seiprotocol.seichain.evm.AddCWERC721PointerProposal") + proto.RegisterType((*AddCWERC1155PointerProposal)(nil), "seiprotocol.seichain.evm.AddCWERC1155PointerProposal") } func init() { proto.RegisterFile("evm/gov.proto", fileDescriptor_fb66eb1aab5c39af) } var fileDescriptor_fb66eb1aab5c39af = []byte{ - // 377 bytes of a gzipped FileDescriptorProto + // 399 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x2d, 0xcb, 0xd5, 0x4f, 0xcf, 0x2f, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x28, 0x4e, 0xcd, 0x04, 0xb3, 0x92, 0xf3, 0x73, 0xf4, 0x8a, 0x53, 0x33, 0x93, 0x33, 0x12, 0x33, 0xf3, 0xf4, 0x52, 0xcb, 0x72, @@ -252,13 +334,14 @@ var fileDescriptor_fb66eb1aab5c39af = []byte{ 0xf2, 0x0c, 0x33, 0x16, 0xc8, 0x33, 0xbc, 0x58, 0x20, 0xcf, 0xa0, 0x34, 0x95, 0x89, 0x4b, 0x12, 0x12, 0x26, 0xce, 0xe1, 0x46, 0x06, 0xf4, 0x0f, 0x11, 0xb8, 0x4f, 0x53, 0xa1, 0x61, 0x82, 0xe1, 0xd3, 0x54, 0xb8, 0x4f, 0x53, 0xe9, 0x18, 0x2e, 0xd3, 0x98, 0xb8, 0xa4, 0x60, 0xe1, 0x62, 0x6e, - 0x64, 0x38, 0x1a, 0x30, 0x68, 0x09, 0xc6, 0x39, 0xdc, 0x35, 0xc8, 0x79, 0x34, 0xc1, 0x60, 0x24, - 0x18, 0x70, 0xb8, 0x8c, 0x26, 0x18, 0x44, 0xc0, 0x38, 0xb9, 0x9f, 0x78, 0x24, 0xc7, 0x78, 0xe1, - 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, - 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x6e, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, - 0x7e, 0x71, 0x6a, 0xa6, 0x2e, 0xac, 0x2c, 0x07, 0x73, 0xc0, 0x85, 0xb9, 0x7e, 0x85, 0x3e, 0xa8, - 0xc8, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0xcb, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, - 0xff, 0xb2, 0xe1, 0xcb, 0x45, 0x06, 0x06, 0x00, 0x00, + 0x64, 0x38, 0x1a, 0x30, 0xb0, 0x80, 0x99, 0x0e, 0xcf, 0x44, 0xce, 0xe1, 0x86, 0x86, 0xa6, 0xa6, + 0xa3, 0x21, 0x83, 0x96, 0x95, 0x9c, 0xc3, 0x5d, 0x83, 0x9c, 0x47, 0xb3, 0x12, 0x46, 0x56, 0x02, + 0x87, 0xcb, 0x68, 0x56, 0xc2, 0xcc, 0x4a, 0xe0, 0x80, 0x19, 0xcd, 0x4a, 0x48, 0x21, 0xe3, 0xe4, + 0x7e, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, + 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xba, 0xe9, 0x99, 0x25, 0x19, + 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xc5, 0xa9, 0x99, 0xba, 0xb0, 0xfa, 0x1f, 0xcc, 0x01, + 0x37, 0x00, 0xf4, 0x2b, 0xf4, 0x41, 0xcd, 0x84, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, + 0xbc, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x06, 0x02, 0xf5, 0x3a, 0x08, 0x00, 0x00, } func (m *AddERCNativePointerProposal) Marshal() (dAtA []byte, err error) { @@ -429,6 +512,62 @@ func (m *AddERCCW721PointerProposal) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *AddERCCW1155PointerProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AddERCCW1155PointerProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AddERCCW1155PointerProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x28 + } + if len(m.Pointer) > 0 { + i -= len(m.Pointer) + copy(dAtA[i:], m.Pointer) + i = encodeVarintGov(dAtA, i, uint64(len(m.Pointer))) + i-- + dAtA[i] = 0x22 + } + if len(m.Pointee) > 0 { + i -= len(m.Pointee) + copy(dAtA[i:], m.Pointee) + i = encodeVarintGov(dAtA, i, uint64(len(m.Pointee))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *AddCWERC20PointerProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -541,6 +680,62 @@ func (m *AddCWERC721PointerProposal) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *AddCWERC1155PointerProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AddCWERC1155PointerProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AddCWERC1155PointerProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x28 + } + if len(m.Pointer) > 0 { + i -= len(m.Pointer) + copy(dAtA[i:], m.Pointer) + i = encodeVarintGov(dAtA, i, uint64(len(m.Pointer))) + i-- + dAtA[i] = 0x22 + } + if len(m.Pointee) > 0 { + i -= len(m.Pointee) + copy(dAtA[i:], m.Pointee) + i = encodeVarintGov(dAtA, i, uint64(len(m.Pointee))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintGov(dAtA []byte, offset int, v uint64) int { offset -= sovGov(v) base := offset @@ -636,6 +831,34 @@ func (m *AddERCCW721PointerProposal) Size() (n int) { return n } +func (m *AddERCCW1155PointerProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Pointee) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Pointer) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if m.Version != 0 { + n += 1 + sovGov(uint64(m.Version)) + } + return n +} + func (m *AddCWERC20PointerProposal) Size() (n int) { if m == nil { return 0 @@ -692,6 +915,34 @@ func (m *AddCWERC721PointerProposal) Size() (n int) { return n } +func (m *AddCWERC1155PointerProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Pointee) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Pointer) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if m.Version != 0 { + n += 1 + sovGov(uint64(m.Version)) + } + return n +} + func sovGov(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1289,7 +1540,7 @@ func (m *AddERCCW721PointerProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *AddCWERC20PointerProposal) Unmarshal(dAtA []byte) error { +func (m *AddERCCW1155PointerProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1312,10 +1563,10 @@ func (m *AddCWERC20PointerProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: AddCWERC20PointerProposal: wiretype end group for non-group") + return fmt.Errorf("proto: AddERCCW1155PointerProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: AddCWERC20PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: AddERCCW1155PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1486,7 +1737,7 @@ func (m *AddCWERC20PointerProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *AddCWERC721PointerProposal) Unmarshal(dAtA []byte) error { +func (m *AddCWERC20PointerProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1509,10 +1760,404 @@ func (m *AddCWERC721PointerProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: AddCWERC721PointerProposal: wiretype end group for non-group") + return fmt.Errorf("proto: AddCWERC20PointerProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: AddCWERC721PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: AddCWERC20PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pointee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pointee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pointer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pointer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AddCWERC721PointerProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AddCWERC721PointerProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AddCWERC721PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pointee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pointee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pointer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pointer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AddCWERC1155PointerProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AddCWERC1155PointerProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AddCWERC1155PointerProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: From f7fa05d4f804246ac7a71dc6973371070b9464b2 Mon Sep 17 00:00:00 2001 From: davyli Date: Fri, 21 Jun 2024 10:43:22 -0400 Subject: [PATCH 14/65] Fix up tests --- precompiles/wasmd/wasmd_test.go | 4 ++-- x/evm/artifacts/cw1155/cw1155.go | 35 ++++++++++++++++++++++++++++++++ x/evm/keeper/grpc_query_test.go | 8 ++++---- x/evm/module_test.go | 2 +- 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 x/evm/artifacts/cw1155/cw1155.go diff --git a/precompiles/wasmd/wasmd_test.go b/precompiles/wasmd/wasmd_test.go index dde3e5114..a38b699fa 100644 --- a/precompiles/wasmd/wasmd_test.go +++ b/precompiles/wasmd/wasmd_test.go @@ -77,7 +77,7 @@ func TestInstantiate(t *testing.T) { outputs, err := instantiateMethod.Outputs.Unpack(res) require.Nil(t, err) require.Equal(t, 2, len(outputs)) - require.Equal(t, "sei1hrpna9v7vs3stzyd4z3xf00676kf78zpe2u5ksvljswn2vnjp3yslucc3n", outputs[0].(string)) + require.Equal(t, "sei18cszlvm6pze0x9sz32qnjq4vtd45xehqs8dq7cwy8yhq35wfnn3quh5sau", outputs[0].(string)) require.Empty(t, outputs[1].([]byte)) require.Equal(t, uint64(881127), g) @@ -100,7 +100,7 @@ func TestInstantiate(t *testing.T) { outputs, err = instantiateMethod.Outputs.Unpack(res) require.Nil(t, err) require.Equal(t, 2, len(outputs)) - require.Equal(t, "sei1hrpna9v7vs3stzyd4z3xf00676kf78zpe2u5ksvljswn2vnjp3yslucc3n", outputs[0].(string)) + require.Equal(t, "sei18cszlvm6pze0x9sz32qnjq4vtd45xehqs8dq7cwy8yhq35wfnn3quh5sau", outputs[0].(string)) require.Empty(t, outputs[1].([]byte)) require.Equal(t, uint64(904183), g) diff --git a/x/evm/artifacts/cw1155/cw1155.go b/x/evm/artifacts/cw1155/cw1155.go new file mode 100644 index 000000000..c043c67dd --- /dev/null +++ b/x/evm/artifacts/cw1155/cw1155.go @@ -0,0 +1,35 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package cw1155 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// Cw721MetaData contains all meta data concerning the Cw721 contract. +var Cw1155MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"Cw721Address_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC721IncorrectOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC721InsufficientApproval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC721InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC721InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC721InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC721InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC721InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC721NonexistentToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplementedOnCosmwasmContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AddrPrecompile\",\"outputs\":[{\"internalType\":\"contractIAddr\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Cw721Address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"JsonPrecompile\",\"outputs\":[{\"internalType\":\"contractIJson\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WasmdPrecompile\",\"outputs\":[{\"internalType\":\"contractIWasmd\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index 94a9318a8..82e0d494d 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -50,10 +50,10 @@ func TestQueryPointer(t *testing.T) { res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_ERC721, Pointee: evmAddr5.Hex()}) require.Nil(t, err) require.Equal(t, types.QueryPointerResponse{Pointer: seiAddr5.String(), Version: uint32(erc721.CurrentVersion), Exists: true}, *res) - res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_CW1155, Pointee: seiAddr3.String()}) + res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_CW1155, Pointee: seiAddr6.String()}) require.Nil(t, err) - require.Equal(t, types.QueryPointerResponse{Pointer: evmAddr3.Hex(), Version: uint32(cw1155.CurrentVersion), Exists: true}, *res) - res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_ERC1155, Pointee: evmAddr5.Hex()}) + require.Equal(t, types.QueryPointerResponse{Pointer: evmAddr6.Hex(), Version: uint32(cw1155.CurrentVersion), Exists: true}, *res) + res, err = q.Pointer(goCtx, &types.QueryPointerRequest{PointerType: types.PointerType_ERC1155, Pointee: evmAddr7.Hex()}) require.Nil(t, err) - require.Equal(t, types.QueryPointerResponse{Pointer: seiAddr5.String(), Version: uint32(erc1155.CurrentVersion), Exists: true}, *res) + require.Equal(t, types.QueryPointerResponse{Pointer: seiAddr7.String(), Version: uint32(erc1155.CurrentVersion), Exists: true}, *res) } diff --git a/x/evm/module_test.go b/x/evm/module_test.go index 02e2509ab..bea7fb23d 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -45,7 +45,7 @@ func TestModuleExportGenesis(t *testing.T) { module := evm.NewAppModule(nil, k) jsonMsg := module.ExportGenesis(ctx, types.ModuleCdc) jsonStr := string(jsonMsg) - assert.Equal(t, "{\"params\":{\"priority_normalizer\":\"1.000000000000000000\",\"base_fee_per_gas\":\"0.000000000000000000\",\"minimum_fee_per_gas\":\"1000000000.000000000000000000\",\"whitelisted_cw_code_hashes_for_delegate_call\":[]},\"address_associations\":[{\"sei_address\":\"sei17xpfvakm2amg962yls6f84z3kell8c5la4jkdu\",\"eth_address\":\"0x27F7B8B8B5A4e71E8E9aA671f4e4031E3773303F\"}],\"codes\":[],\"states\":[],\"nonces\":[],\"serialized\":[{\"prefix\":\"Fg==\",\"key\":\"AwAB\",\"value\":\"AAAAAAAAAAM=\"},{\"prefix\":\"Fg==\",\"key\":\"BAAF\",\"value\":\"AAAAAAAAAAQ=\"}]}", jsonStr) + assert.Equal(t, "{\"params\":{\"priority_normalizer\":\"1.000000000000000000\",\"base_fee_per_gas\":\"0.000000000000000000\",\"minimum_fee_per_gas\":\"1000000000.000000000000000000\",\"whitelisted_cw_code_hashes_for_delegate_call\":[]},\"address_associations\":[{\"sei_address\":\"sei17xpfvakm2amg962yls6f84z3kell8c5la4jkdu\",\"eth_address\":\"0x27F7B8B8B5A4e71E8E9aA671f4e4031E3773303F\"}],\"codes\":[],\"states\":[],\"nonces\":[],\"serialized\":[{\"prefix\":\"Fg==\",\"key\":\"AwAB\",\"value\":\"AAAAAAAAAAQ=\"},{\"prefix\":\"Fg==\",\"key\":\"BAAF\",\"value\":\"AAAAAAAAAAU=\"},{\"prefix\":\"Fg==\",\"key\":\"BgAB\",\"value\":\"AAAAAAAAAAY=\"}]}", jsonStr) } func TestConsensusVersion(t *testing.T) { From ae6a0953cb0061f12297b5d3cda9e2d4c239d469 Mon Sep 17 00:00:00 2001 From: davyli Date: Fri, 21 Jun 2024 15:26:28 -0400 Subject: [PATCH 15/65] Deprecate pointer proposals --- x/evm/gov.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/x/evm/gov.go b/x/evm/gov.go index c34ac5866..e62e796d3 100644 --- a/x/evm/gov.go +++ b/x/evm/gov.go @@ -103,15 +103,7 @@ func HandleAddERCCW721PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *type } func HandleAddERCCW1155PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddERCCW1155PointerProposal) error { - ctx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "cw1155"), - sdk.NewAttribute(types.AttributeKeyPointerAddress, p.Pointer), sdk.NewAttribute(types.AttributeKeyPointee, p.Pointee), - sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", p.Version)))) - if p.Pointer == "" { - k.DeleteERC1155CW1155Pointer(ctx, p.Pointee, uint16(p.Version)) - return nil - } - return k.SetERC1155CW1155PointerWithVersion(ctx, p.Pointee, common.HexToAddress(p.Pointer), uint16(p.Version)) + return errors.New("proposal type deprecated") } func HandleAddCWERC20PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddCWERC20PointerProposal) error { @@ -123,13 +115,5 @@ func HandleAddCWERC721PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *type } func HandleAddCWERC1155PointerProposal(ctx sdk.Context, k *keeper.Keeper, p *types.AddCWERC1155PointerProposal) error { - ctx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypePointerRegistered, sdk.NewAttribute(types.AttributeKeyPointerType, "erc1155"), - sdk.NewAttribute(types.AttributeKeyPointerAddress, p.Pointer), sdk.NewAttribute(types.AttributeKeyPointee, p.Pointee), - sdk.NewAttribute(types.AttributeKeyPointerVersion, fmt.Sprintf("%d", p.Version)))) - if p.Pointer == "" { - k.DeleteCW1155ERC1155Pointer(ctx, common.HexToAddress(p.Pointee), uint16(p.Version)) - return nil - } - return k.SetCW1155ERC1155PointerWithVersion(ctx, common.HexToAddress(p.Pointee), p.Pointer, uint16(p.Version)) + return errors.New("proposal type deprecated") } From 5082b6b00b788cbd75b3e9a493abd9f953e95ef4 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Thu, 20 Jun 2024 20:57:24 +0100 Subject: [PATCH 16/65] queries --- contracts/src/CW1155ERC1155Pointer.sol | 102 +++++++++ .../test/CW1155toERC1155PointerTest.t.sol | 204 ++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 contracts/src/CW1155ERC1155Pointer.sol create mode 100644 contracts/test/CW1155toERC1155PointerTest.t.sol diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol new file mode 100644 index 000000000..caa15ae3d --- /dev/null +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import "@openzeppelin/contracts/token/common/ERC2981.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IWasmd} from "./precompiles/IWasmd.sol"; +import {IJson} from "./precompiles/IJson.sol"; +import {IAddr} from "./precompiles/IAddr.sol"; + + +contract CW1155ERC1155Pointer is ERC1155, ERC2981 { + + address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; + address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; + address constant ADDR_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001004; + + string public Cw1155Address; + IWasmd public WasmdPrecompile; + IJson public JsonPrecompile; + IAddr public AddrPrecompile; + + error NotImplementedOnCosmwasmContract(string method); + error NotImplemented(string method); + + constructor(string memory Cw1155Address_, string memory uri_) ERC1155(uri_) { + WasmdPrecompile = IWasmd(WASMD_PRECOMPILE_ADDRESS); + JsonPrecompile = IJson(JSON_PRECOMPILE_ADDRESS); + AddrPrecompile = IAddr(ADDR_PRECOMPILE_ADDRESS); + Cw1155Address = Cw1155Address_; + } + + function supportsInterface(bytes4 interfaceId) public pure override(ERC2981, ERC1155) returns (bool) { + return + interfaceId == type(IERC2981).interfaceId || + interfaceId == type(IERC1155).interfaceId || + interfaceId == type(IERC1155MetadataURI).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + + // Queries + function balanceOf(address account, uint256 id) public view override returns (uint256) { + require(account != address(0), "ERC1155: cannot query balance of zero address"); + string memory req = _curlyBrace( + _keyValue("balance_of",(_curlyBrace( + _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))),",",_keyValue("token_id", _doubleQuotes(Strings.toString(id)))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return JsonPrecompile.extractAsUint256(response, "balance"); + } + + function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view override returns (uint256[] memory balances){ + if(accounts.length != ids.length){ + revert ERC1155InvalidArrayLength(ids.length, accounts.length); + } + balances = new uint256[](accounts.length); + for(uint256 i = 0; i < accounts.length; i++){ + balances[i] = balanceOf(accounts[i], ids[i]); + } + } + + function uri(uint256 id) public view override returns (string memory) { + string memory req = _curlyBrace( + _keyValue("token_info",(_curlyBrace( + _keyValue("token_id", _doubleQuotes(Strings.toString(id))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return string(JsonPrecompile.extractAsBytes(response, "token_uri")); + } + + function isApprovedForAll(address owner, address operator) public view override returns (bool) { + string memory req = _curlyBrace( + _keyValue("is_approved_for_all",(_curlyBrace( + _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))),",",_keyValue("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator)))) + ))) + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); + return JsonPrecompile.extractAsUint256(response, "approved") == 1; + } + + + function _keyValue(string memory key, string memory value) internal pure returns (string memory) { + return _join(_doubleQuotes(key), ":", value); + } + + function _curlyBrace(string memory s) internal pure returns (string memory) { + return string.concat("{", string.concat(s, "}")); + } + + function _doubleQuotes(string memory s) internal pure returns (string memory) { + return string.concat("\"", string.concat(s, "\"")); + } + + function _join(string memory a, string memory separator, string memory b) internal pure returns (string memory) { + return string.concat(a, string.concat(separator, b)); + } +} diff --git a/contracts/test/CW1155toERC1155PointerTest.t.sol b/contracts/test/CW1155toERC1155PointerTest.t.sol new file mode 100644 index 000000000..9f9a12bc5 --- /dev/null +++ b/contracts/test/CW1155toERC1155PointerTest.t.sol @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test, console2} from "forge-std/Test.sol"; +import {CW1155ERC1155Pointer} from "../src/CW1155ERC1155Pointer.sol"; +import {IWasmd} from "../src/precompiles/IWasmd.sol"; +import {IJson} from "../src/precompiles/IJson.sol"; +import {IAddr} from "../src/precompiles/IAddr.sol"; +import "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; + +address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; +address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; +address constant ADDR_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001004; + +address constant MockCallerEVMAddr = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; +address constant MockOperatorEVMAddr = 0xF39fD6e51Aad88F6f4CE6AB8827279CFffb92267; +address constant MockZeroAddress = 0x0000000000000000000000000000000000000000; + +string constant MockCallerSeiAddr = "sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw"; +string constant MockOperatorSeiAddr = "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"; +string constant MockCWContractAddress = "sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m"; + +contract MockWasmd is IWasmd { + + // Transactions + function instantiate( + uint64, + string memory, + bytes memory, + string memory, + bytes memory + ) external pure returns (string memory, bytes memory) { + return (MockCWContractAddress, bytes("")); + } + + function execute( + string memory contractAddress, + bytes memory, + bytes memory + ) external pure returns (bytes memory) { + require(keccak256(abi.encodePacked(contractAddress)) == keccak256(abi.encodePacked(MockCWContractAddress)), "wrong CW contract address"); + return bytes(""); + } + + // Queries + function query(string memory, bytes memory) external pure returns (bytes memory) { + return bytes(""); + } +} + +contract MockJson is IJson { + function extractAsBytes(bytes memory, string memory) external pure returns (bytes memory) { + return bytes("extracted bytes"); + } + + function extractAsBytesList(bytes memory, string memory) external pure returns (bytes[] memory) { + return new bytes[](0); + } + + function extractAsUint256(bytes memory input, string memory key) external view returns (uint256 response) { + return 0; + } +} + +contract MockAddr is IAddr { + function getSeiAddr(address addr) external pure returns (string memory) { + if (addr == MockCallerEVMAddr) { + return MockCallerSeiAddr; + } + return MockOperatorSeiAddr; + } + + function getEvmAddr(string memory addr) external pure returns (address) { + if (keccak256(abi.encodePacked(addr)) == keccak256(abi.encodePacked(MockCallerSeiAddr))) { + return MockCallerEVMAddr; + } + return MockOperatorEVMAddr; + } +} + +contract CW1155ERC1155PointerTest is Test { + CW1155ERC1155Pointer pointer; + MockWasmd mockWasmd; + MockJson mockJson; + MockAddr mockAddr; + + function setUp() public { + pointer = new CW1155ERC1155Pointer(MockCWContractAddress, "ipfs://uri.json"); + mockWasmd = new MockWasmd(); + mockJson = new MockJson(); + mockAddr = new MockAddr(); + vm.etch(WASMD_PRECOMPILE_ADDRESS, address(mockWasmd).code); + vm.etch(JSON_PRECOMPILE_ADDRESS, address(mockJson).code); + vm.etch(ADDR_PRECOMPILE_ADDRESS, address(mockAddr).code); + } + + function testBalanceOf() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + assertEq(pointer.balanceOf(MockCallerEVMAddr, 1), 1); + } + + function testBalanceOfZeroAddress() public { + vm.expectRevert(bytes("ERC1155: cannot query balance of zero address")); + pointer.balanceOf(MockZeroAddress, 1); + } + + function testBalanceOfBatch() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"2\"}}")), + abi.encode("{\"balance\":\"2\"}") + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"3\"}}")), + abi.encode("{\"balance\":\"0\"}") + ); + + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"2\"}"), "balance"), + abi.encode(2) + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"0\"}"), "balance"), + abi.encode(0) + ); + address[] memory owners = new address[](3); + uint256[] memory ids = new uint256[](3); + owners[0] = MockCallerEVMAddr; + owners[1] = MockCallerEVMAddr; + owners[2] = MockCallerEVMAddr; + ids[0] = 1; + ids[1] = 2; + ids[2] = 3; + uint256[] memory expectedResp = new uint256[](3); + expectedResp[0] = 1; + expectedResp[1] = 2; + expectedResp[2] = 0; + assertEq(pointer.balanceOfBatch(owners, ids), expectedResp); + } + + function testBatchBalanceOfBadLength() public { + uint256 idsLength = 1; + uint256 valuesLength = 0; + vm.expectRevert( + abi.encodeWithSelector( + IERC1155Errors.ERC1155InvalidArrayLength.selector, + idsLength, + valuesLength + ) + ); + pointer.balanceOfBatch(new address[](valuesLength), new uint256[](idsLength)); + } + + function testUri() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"token_info\":{\"token_id\":\"1\"}}")), + abi.encode("{\"extension\": { \"animation_url\": null, \"attributes\": null, \"background_color\": null, \"description\": null, \"external_url\": null, \"image\": null, \"image_data\": null, \"name\": null, \"royalty_payment_address\": null, \"royalty_percentage\": null, \"youtube_url\": null }, \"token_uri\": \"test\" }") + ); + + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsBytes(bytes,string)", bytes("{\"extension\": { \"animation_url\": null, \"attributes\": null, \"background_color\": null, \"description\": null, \"external_url\": null, \"image\": null, \"image_data\": null, \"name\": null, \"royalty_payment_address\": null, \"royalty_percentage\": null, \"youtube_url\": null }, \"token_uri\": \"test\" }"), "token_uri"), + abi.encode(bytes("test")) + ); + assertEq(pointer.uri(1), "test"); + } + + function testIsApprovedForAll() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"is_approved_for_all\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"operator\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\"}}")), + abi.encode("{\"approved\":true}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"approved\":true}"), "approved"), + abi.encode(true) + ); + assertEq(pointer.isApprovedForAll(MockCallerEVMAddr, MockOperatorEVMAddr), true); + } +} \ No newline at end of file From cb2ba41d74fb2ebf2755c64104e23df2cf667ed6 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Thu, 20 Jun 2024 21:12:25 +0100 Subject: [PATCH 17/65] follow same coding style --- contracts/src/CW1155ERC1155Pointer.sol | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index caa15ae3d..7513fbacf 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -44,11 +44,9 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { // Queries function balanceOf(address account, uint256 id) public view override returns (uint256) { require(account != address(0), "ERC1155: cannot query balance of zero address"); - string memory req = _curlyBrace( - _keyValue("balance_of",(_curlyBrace( - _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))),",",_keyValue("token_id", _doubleQuotes(Strings.toString(id)))) - ))) - ); + string memory own = _formatPayload("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(account))); + string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(id))); + string memory req = _curlyBrace(_formatPayload("balance_of",(_curlyBrace(_join(own,",",tId))))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return JsonPrecompile.extractAsUint256(response, "balance"); } @@ -64,27 +62,22 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { } function uri(uint256 id) public view override returns (string memory) { - string memory req = _curlyBrace( - _keyValue("token_info",(_curlyBrace( - _keyValue("token_id", _doubleQuotes(Strings.toString(id))) - ))) - ); + string memory tId = _curlyBrace(_formatPayload("token_id", _doubleQuotes(Strings.toString(id)))); + string memory req = _curlyBrace(_formatPayload("token_info",(tId))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return string(JsonPrecompile.extractAsBytes(response, "token_uri")); } function isApprovedForAll(address owner, address operator) public view override returns (bool) { - string memory req = _curlyBrace( - _keyValue("is_approved_for_all",(_curlyBrace( - _join(_keyValue("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))),",",_keyValue("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator)))) - ))) - ); + string memory own = _formatPayload("owner", _doubleQuotes(AddrPrecompile.getSeiAddr(owner))); + string memory op = _formatPayload("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator))); + string memory req = _curlyBrace(_formatPayload("is_approved_for_all",(_curlyBrace(_join(own,",",op))))); bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(req)); return JsonPrecompile.extractAsUint256(response, "approved") == 1; } - function _keyValue(string memory key, string memory value) internal pure returns (string memory) { + function _formatPayload(string memory key, string memory value) internal pure returns (string memory) { return _join(_doubleQuotes(key), ":", value); } From d260408990a56d578c660ecbf2799391946eb9d1 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Tue, 25 Jun 2024 20:46:05 +0100 Subject: [PATCH 18/65] safetransfer functions, royalyinfo, set approval --- contracts/src/CW1155ERC1155Pointer.sol | 102 ++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index 7513fbacf..69f3badf7 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -5,6 +5,8 @@ import "@openzeppelin/contracts/token/common/ERC2981.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IWasmd} from "./precompiles/IWasmd.sol"; @@ -12,7 +14,7 @@ import {IJson} from "./precompiles/IJson.sol"; import {IAddr} from "./precompiles/IAddr.sol"; -contract CW1155ERC1155Pointer is ERC1155, ERC2981 { +contract CW1155ERC1155Pointer is ERC1155, ERC2981, ReentrancyGuard { address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; @@ -76,6 +78,104 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { return JsonPrecompile.extractAsUint256(response, "approved") == 1; } + // 2981 + function royaltyInfo(uint256 tokenId, uint256 salePrice) public view override returns (address, uint256) { + bytes memory checkRoyaltyResponse = WasmdPrecompile.query(Cw1155Address, bytes("{\"extension\":{\"msg\":{\"check_royalties\":{}}}}")); + bytes memory isRoyaltyImplemented = JsonPrecompile.extractAsBytes(checkRoyaltyResponse, "royalty_payments"); + if (keccak256(isRoyaltyImplemented) != keccak256("true")) { + revert NotImplementedOnCosmwasmContract("royalty_info"); + } + string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(tokenId))); + string memory sPrice = _formatPayload("sale_price", _doubleQuotes(Strings.toString(salePrice))); + string memory req = _curlyBrace(_formatPayload("royalty_info", _curlyBrace(_join(tId, sPrice, ",")))); + string memory fullReq = _curlyBrace(_formatPayload("extension", _curlyBrace(_formatPayload("msg", req)))); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(fullReq)); + bytes memory addr = JsonPrecompile.extractAsBytes(response, "address"); + uint256 amt = JsonPrecompile.extractAsUint256(response, "royalty_amount"); + if (addr.length == 0) { + return (address(0), amt); + } + return (AddrPrecompile.getEvmAddr(string(addr)), amt); + } + + //transactions + function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) public override nonReentrant { + require(to != address(0), "ERC1155: transfer to the zero address"); + require(balanceOf(from, id) >= amount, "ERC1155: insufficient balance for transfer"); + require(msg.sender == from || isApprovedForAll(from, msg.sender), "ERC1155: caller is not approved to transfer"); + if (to.code.length > 0) { + require( + IERC1155Receiver(to).onERC1155Received( + msg.sender, from, id, amount, data + ) == IERC1155Receiver.onERC1155Received.selector, + "unsafe transfer" + ); + } + + string memory f = _formatPayload("from", _doubleQuotes(AddrPrecompile.getSeiAddr(from))); + string memory t = _formatPayload("to", _doubleQuotes(AddrPrecompile.getSeiAddr(to))); + string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(id))); + string memory amt = _formatPayload("amount", _doubleQuotes(Strings.toString(amount))); + + string memory req = _curlyBrace(_formatPayload("send",(_curlyBrace(_join(f,",",_join(t,",",_join(tId,",",amt))))))); + _execute(bytes(req)); + emit TransferSingle(msg.sender, from, to, id, amount); + } + + function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public override nonReentrant{ + require(to != address(0), "ERC1155: transfer to the zero address"); + require(isApprovedForAll(from, address(this)), "ERC1155: caller is not approved to transfer"); + require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); + if (to.code.length > 0) { + require( + IERC1155Receiver(to).onERC1155BatchReceived( + msg.sender, from, ids, amounts, data + ) == IERC1155Receiver.onERC1155Received.selector, + "unsafe transfer" + ); + } + + for(uint256 i = 0; i < ids.length; i++){ + require(balanceOf(from, ids[i]) >= amounts[i], "ERC1155: insufficient balance for transfer"); + } + + string memory f = _formatPayload("from", _doubleQuotes(AddrPrecompile.getSeiAddr(from))); + string memory t = _formatPayload("to", _doubleQuotes(AddrPrecompile.getSeiAddr(to))); + string memory tokenAmount = _formatPayload("token_amount", "["); + for(uint256 i = 0; i < ids.length; i++){ + string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(ids[i]))); + string memory amt = _formatPayload("amount", _doubleQuotes(Strings.toString(amounts[i]))); + string.concat(tokenAmount, _curlyBrace(_join(tId,",",amt))); + } + string.concat(tokenAmount, "]"); + string memory req = _curlyBrace(_formatPayload("send_batch",(_curlyBrace(_join(f,",",_join(t,",",tokenAmount)))))); + + _execute(bytes(req)); + emit TransferBatch(msg.sender, from, to, ids, amounts); + } + + function setApprovalForAll(address operator, bool approved) public override { + string memory op = _curlyBrace(_formatPayload("operator", _doubleQuotes(AddrPrecompile.getSeiAddr(operator)))); + if (approved) { + _execute(bytes(_curlyBrace(_formatPayload("approve_all", op)))); + } else { + _execute(bytes(_curlyBrace(_formatPayload("revoke_all", op)))); + } + emit ApprovalForAll(msg.sender, operator, approved); + } + + function _execute(bytes memory req) internal returns (bytes memory) { + (bool success, bytes memory ret) = WASMD_PRECOMPILE_ADDRESS.delegatecall( + abi.encodeWithSignature( + "execute(string,bytes,bytes)", + Cw1155Address, + bytes(req), + bytes("[]") + ) + ); + require(success, "CosmWasm execute failed"); + return ret; + } function _formatPayload(string memory key, string memory value) internal pure returns (string memory) { return _join(_doubleQuotes(key), ":", value); From 1ee0e92b4412035512682178531d659f3e61da79 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:44:24 +0100 Subject: [PATCH 19/65] adding in transfer and approval tests --- contracts/src/CW1155ERC1155Pointer.sol | 2 +- .../test/CW1155toERC1155PointerTest.t.sol | 148 ++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index e77d085ae..c8d576c0c 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -124,7 +124,7 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public override { require(to != address(0), "ERC1155: transfer to the zero address"); - require(isApprovedForAll(from, address(this)), "ERC1155: caller is not approved to transfer"); + require(msg.sender == from || isApprovedForAll(from, msg.sender), "ERC1155: caller is not approved to transfer"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); for(uint256 i = 0; i < ids.length; i++){ diff --git a/contracts/test/CW1155toERC1155PointerTest.t.sol b/contracts/test/CW1155toERC1155PointerTest.t.sol index 9f9a12bc5..c62d08fee 100644 --- a/contracts/test/CW1155toERC1155PointerTest.t.sol +++ b/contracts/test/CW1155toERC1155PointerTest.t.sol @@ -79,6 +79,11 @@ contract MockAddr is IAddr { } contract CW1155ERC1155PointerTest is Test { + + event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); + event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + CW1155ERC1155Pointer pointer; MockWasmd mockWasmd; MockJson mockJson; @@ -201,4 +206,147 @@ contract CW1155ERC1155PointerTest is Test { ); assertEq(pointer.isApprovedForAll(MockCallerEVMAddr, MockOperatorEVMAddr), true); } + + function testSafeTransferFrom() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw"), + abi.encode(address(MockCallerEVMAddr)) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"), + abi.encode(address(MockOperatorEVMAddr)) + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"send\":{\"from\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"to\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\",\"token_id\":\"1\",\"amount\":\"1\"}}")), + abi.encode(bytes("")) + ); + vm.expectEmit(); + emit TransferSingle(MockCallerEVMAddr, MockCallerEVMAddr, MockOperatorEVMAddr, 1, 1); + vm.startPrank(MockCallerEVMAddr); + pointer.safeTransferFrom(MockCallerEVMAddr, MockOperatorEVMAddr, 1, 1, bytes("")); + vm.stopPrank(); + } + + function testSafeTransferFromWithOperator() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"is_approved_for_all\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"operator\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\"}}")), + abi.encode("{\"approved\":true}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"approved\":true}"), "approved"), + abi.encode(true) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw"), + abi.encode(address(MockCallerEVMAddr)) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"), + abi.encode(address(MockOperatorEVMAddr)) + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"send\":{\"from\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"to\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\",\"token_id\":\"1\",\"amount\":\"1\"}}")), + abi.encode(bytes("")) + ); + vm.expectEmit(); + emit TransferSingle(MockOperatorEVMAddr, MockCallerEVMAddr, MockOperatorEVMAddr, 1, 1); + vm.startPrank(MockOperatorEVMAddr); + pointer.safeTransferFrom(MockCallerEVMAddr, MockOperatorEVMAddr, 1, 1, bytes("")); + vm.stopPrank(); + } + + function testSafeBatchTransferFrom() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"1\"}}")), + abi.encode("{\"balance\":\"1\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"1\"}"), "balance"), + abi.encode(1) + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("query(string,bytes)", MockCWContractAddress, bytes("{\"balance_of\":{\"owner\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"token_id\":\"2\"}}")), + abi.encode("{\"balance\":\"2\"}") + ); + vm.mockCall( + JSON_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("extractAsUint256(bytes,string)", bytes("{\"balance\":\"2\"}"), "balance"), + abi.encode(2) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw"), + abi.encode(address(MockCallerEVMAddr)) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"), + abi.encode(address(MockOperatorEVMAddr)) + ); + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"send\":{\"from\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"to\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\",\"token_id\":\"1\",\"amount\":\"1\"}}")), + abi.encode(bytes("")) + ); + uint256[] memory ids = new uint256[](2); + uint256[] memory amounts = new uint256[](2); + ids[0] = 1; + ids[1] = 2; + amounts[0] = 1; + amounts[1] = 2; + vm.expectEmit(); + emit TransferBatch(MockCallerEVMAddr, MockCallerEVMAddr, MockOperatorEVMAddr, ids, amounts); + vm.startPrank(MockCallerEVMAddr); + pointer.safeBatchTransferFrom(MockCallerEVMAddr, MockOperatorEVMAddr, ids, amounts, bytes("")); + vm.stopPrank(); + } + + function testSetApprovalForAll() public { + vm.mockCall( + WASMD_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"approval_all\":{\"operator\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\"}}"), bytes("[]")), + abi.encode(bytes("")) + ); + vm.mockCall( + ADDR_PRECOMPILE_ADDRESS, + abi.encodeWithSignature("getEvmAddr(string)", "sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe"), + abi.encode(address(MockOperatorEVMAddr)) + ); + vm.startPrank(MockCallerEVMAddr); + vm.expectEmit(); + emit ApprovalForAll(MockCallerEVMAddr, MockOperatorEVMAddr, true); + pointer.setApprovalForAll(MockOperatorEVMAddr, true); + vm.stopPrank(); + } } \ No newline at end of file From 1d91ef5aee1f1caa269a657b4918009d1cde7910 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Wed, 26 Jun 2024 01:02:33 +0100 Subject: [PATCH 20/65] solc and abigen --- x/evm/artifacts/cw1155/Arrays.abi | 1 + x/evm/artifacts/cw1155/Arrays.bin | 1 + .../artifacts/cw1155/CW1155ERC1155Pointer.abi | 1 + .../artifacts/cw1155/CW1155ERC1155Pointer.bin | 1 + x/evm/artifacts/cw1155/Context.abi | 1 + x/evm/artifacts/cw1155/Context.bin | 0 x/evm/artifacts/cw1155/ERC1155.abi | 1 + x/evm/artifacts/cw1155/ERC1155.bin | 0 x/evm/artifacts/cw1155/ERC165.abi | 1 + x/evm/artifacts/cw1155/ERC165.bin | 0 x/evm/artifacts/cw1155/ERC2981.abi | 1 + x/evm/artifacts/cw1155/ERC2981.bin | 0 x/evm/artifacts/cw1155/IAddr.abi | 1 + x/evm/artifacts/cw1155/IAddr.bin | 0 x/evm/artifacts/cw1155/IERC1155.abi | 1 + x/evm/artifacts/cw1155/IERC1155.bin | 0 x/evm/artifacts/cw1155/IERC1155Errors.abi | 1 + x/evm/artifacts/cw1155/IERC1155Errors.bin | 0 .../artifacts/cw1155/IERC1155MetadataURI.abi | 1 + .../artifacts/cw1155/IERC1155MetadataURI.bin | 0 x/evm/artifacts/cw1155/IERC1155Receiver.abi | 1 + x/evm/artifacts/cw1155/IERC1155Receiver.bin | 0 x/evm/artifacts/cw1155/IERC165.abi | 1 + x/evm/artifacts/cw1155/IERC165.bin | 0 x/evm/artifacts/cw1155/IERC20Errors.abi | 1 + x/evm/artifacts/cw1155/IERC20Errors.bin | 0 x/evm/artifacts/cw1155/IERC2981.abi | 1 + x/evm/artifacts/cw1155/IERC2981.bin | 0 x/evm/artifacts/cw1155/IERC721Errors.abi | 1 + x/evm/artifacts/cw1155/IERC721Errors.bin | 0 x/evm/artifacts/cw1155/IJson.abi | 1 + x/evm/artifacts/cw1155/IJson.bin | 0 x/evm/artifacts/cw1155/IWasmd.abi | 1 + x/evm/artifacts/cw1155/IWasmd.bin | 0 x/evm/artifacts/cw1155/Math.abi | 1 + x/evm/artifacts/cw1155/Math.bin | 1 + x/evm/artifacts/cw1155/SignedMath.abi | 1 + x/evm/artifacts/cw1155/SignedMath.bin | 1 + x/evm/artifacts/cw1155/StorageSlot.abi | 1 + x/evm/artifacts/cw1155/StorageSlot.bin | 1 + x/evm/artifacts/cw1155/Strings.abi | 1 + x/evm/artifacts/cw1155/Strings.bin | 1 + x/evm/artifacts/cw1155/cw1155.go | 1151 ++++++++++++++++- 43 files changed, 1176 insertions(+), 2 deletions(-) create mode 100644 x/evm/artifacts/cw1155/Arrays.abi create mode 100644 x/evm/artifacts/cw1155/Arrays.bin create mode 100644 x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi create mode 100644 x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin create mode 100644 x/evm/artifacts/cw1155/Context.abi create mode 100644 x/evm/artifacts/cw1155/Context.bin create mode 100644 x/evm/artifacts/cw1155/ERC1155.abi create mode 100644 x/evm/artifacts/cw1155/ERC1155.bin create mode 100644 x/evm/artifacts/cw1155/ERC165.abi create mode 100644 x/evm/artifacts/cw1155/ERC165.bin create mode 100644 x/evm/artifacts/cw1155/ERC2981.abi create mode 100644 x/evm/artifacts/cw1155/ERC2981.bin create mode 100644 x/evm/artifacts/cw1155/IAddr.abi create mode 100644 x/evm/artifacts/cw1155/IAddr.bin create mode 100644 x/evm/artifacts/cw1155/IERC1155.abi create mode 100644 x/evm/artifacts/cw1155/IERC1155.bin create mode 100644 x/evm/artifacts/cw1155/IERC1155Errors.abi create mode 100644 x/evm/artifacts/cw1155/IERC1155Errors.bin create mode 100644 x/evm/artifacts/cw1155/IERC1155MetadataURI.abi create mode 100644 x/evm/artifacts/cw1155/IERC1155MetadataURI.bin create mode 100644 x/evm/artifacts/cw1155/IERC1155Receiver.abi create mode 100644 x/evm/artifacts/cw1155/IERC1155Receiver.bin create mode 100644 x/evm/artifacts/cw1155/IERC165.abi create mode 100644 x/evm/artifacts/cw1155/IERC165.bin create mode 100644 x/evm/artifacts/cw1155/IERC20Errors.abi create mode 100644 x/evm/artifacts/cw1155/IERC20Errors.bin create mode 100644 x/evm/artifacts/cw1155/IERC2981.abi create mode 100644 x/evm/artifacts/cw1155/IERC2981.bin create mode 100644 x/evm/artifacts/cw1155/IERC721Errors.abi create mode 100644 x/evm/artifacts/cw1155/IERC721Errors.bin create mode 100644 x/evm/artifacts/cw1155/IJson.abi create mode 100644 x/evm/artifacts/cw1155/IJson.bin create mode 100644 x/evm/artifacts/cw1155/IWasmd.abi create mode 100644 x/evm/artifacts/cw1155/IWasmd.bin create mode 100644 x/evm/artifacts/cw1155/Math.abi create mode 100644 x/evm/artifacts/cw1155/Math.bin create mode 100644 x/evm/artifacts/cw1155/SignedMath.abi create mode 100644 x/evm/artifacts/cw1155/SignedMath.bin create mode 100644 x/evm/artifacts/cw1155/StorageSlot.abi create mode 100644 x/evm/artifacts/cw1155/StorageSlot.bin create mode 100644 x/evm/artifacts/cw1155/Strings.abi create mode 100644 x/evm/artifacts/cw1155/Strings.bin diff --git a/x/evm/artifacts/cw1155/Arrays.abi b/x/evm/artifacts/cw1155/Arrays.abi new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/x/evm/artifacts/cw1155/Arrays.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Arrays.bin b/x/evm/artifacts/cw1155/Arrays.bin new file mode 100644 index 000000000..15ba16e72 --- /dev/null +++ b/x/evm/artifacts/cw1155/Arrays.bin @@ -0,0 +1 @@ +6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea26469706673582212201aad5655fee17ba323abb11a28d38fccb4e505a23222c48e002b0b021e21522964736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi new file mode 100644 index 000000000..b76de76e1 --- /dev/null +++ b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"Cw1155Address_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplemented","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplementedOnCosmwasmContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"AddrPrecompile","outputs":[{"internalType":"contract IAddr","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Cw1155Address","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"JsonPrecompile","outputs":[{"internalType":"contract IJson","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WasmdPrecompile","outputs":[{"internalType":"contract IWasmd","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin new file mode 100644 index 000000000..e890a5278 --- /dev/null +++ b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin @@ -0,0 +1 @@ +608060405234801561000f575f80fd5b5060405161499c38038061499c8339818101604052810190610031919061027f565b806100418161011f60201b60201c565b5061100260065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100460085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600590816101179190610502565b5050506105d1565b806002908161012e9190610502565b5050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101918261014b565b810181811067ffffffffffffffff821117156101b0576101af61015b565b5b80604052505050565b5f6101c2610132565b90506101ce8282610188565b919050565b5f67ffffffffffffffff8211156101ed576101ec61015b565b5b6101f68261014b565b9050602081019050919050565b8281835e5f83830152505050565b5f61022361021e846101d3565b6101b9565b90508281526020810184848401111561023f5761023e610147565b5b61024a848285610203565b509392505050565b5f82601f83011261026657610265610143565b5b8151610276848260208601610211565b91505092915050565b5f80604083850312156102955761029461013b565b5b5f83015167ffffffffffffffff8111156102b2576102b161013f565b5b6102be85828601610252565b925050602083015167ffffffffffffffff8111156102df576102de61013f565b5b6102eb85828601610252565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061034357607f821691505b602082108103610356576103556102ff565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026103b87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261037d565b6103c2868361037d565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104066104016103fc846103da565b6103e3565b6103da565b9050919050565b5f819050919050565b61041f836103ec565b61043361042b8261040d565b848454610389565b825550505050565b5f90565b61044761043b565b610452818484610416565b505050565b5b818110156104755761046a5f8261043f565b600181019050610458565b5050565b601f8211156104ba5761048b8161035c565b6104948461036e565b810160208510156104a3578190505b6104b76104af8561036e565b830182610457565b50505b505050565b5f82821c905092915050565b5f6104da5f19846008026104bf565b1980831691505092915050565b5f6104f283836104cb565b9150826002028217905092915050565b61050b826102f5565b67ffffffffffffffff8111156105245761052361015b565b5b61052e825461032c565b610539828285610479565b5f60209050601f83116001811461056a575f8415610558578287015190505b61056285826104e7565b8655506105c9565b601f1984166105788661035c565b5f5b8281101561059f5784890151825560018201915060208501945060208101905061057a565b868310156105bc57848901516105b8601f8916826104cb565b8355505b6001600288020188555050505b505050505050565b6143be806105de5f395ff3fe608060405234801561000f575f80fd5b50600436106100cc575f3560e01c8063a22cb4651161008a578063de4725cc11610064578063de4725cc14610235578063e985e9c514610253578063f00b025514610283578063f242432a146102a1576100cc565b8063a22cb465146101dd578063b98933a0146101f9578063c2aed30214610217576100cc565b8062fdd58e146100d057806301ffc9a7146101005780630e89341c146101305780632a55205a146101605780632eb2c2d6146101915780634e1273f4146101ad575b5f80fd5b6100ea60048036038101906100e59190612b9e565b6102bd565b6040516100f79190612beb565b60405180910390f35b61011a60048036038101906101159190612c59565b61063b565b6040516101279190612c9e565b60405180910390f35b61014a60048036038101906101459190612cb7565b6107dc565b6040516101579190612d52565b60405180910390f35b61017a60048036038101906101759190612d72565b6109ca565b604051610188929190612dbf565b60405180910390f35b6101ab60048036038101906101a69190612fd6565b610ffb565b005b6101c760048036038101906101c29190613161565b61180e565b6040516101d4919061328e565b60405180910390f35b6101f760048036038101906101f291906132d8565b611922565b005b610201611b25565b60405161020e9190612d52565b60405180910390f35b61021f611bb1565b60405161022c9190613371565b60405180910390f35b61023d611bd6565b60405161024a91906133aa565b60405180910390f35b61026d600480360381019061026891906133c3565b611bfb565b60405161027a9190612c9e565b60405180910390f35b61028b611fa1565b6040516102989190613421565b60405180910390f35b6102bb60048036038101906102b6919061343a565b611fc6565b005b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361032c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103239061353d565b60405180910390fd5b5f61040f6040518060400160405280600581526020017f6f776e657200000000000000000000000000000000000000000000000000000081525061040a60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016103c3919061355b565b5f60405180830381865afa1580156103dd573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906104059190613612565b612637565b61267f565b90505f6104616040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061045c610457876126d1565b612637565b61267f565b90505f6104f26104ed6040518060400160405280600a81526020017f62616c616e63655f6f66000000000000000000000000000000000000000000008152506104e86104e3876040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508861279b565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b815260040161055292919061379b565b5f60405180830381865afa15801561056c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610594919061383e565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982826040518263ffffffff1660e01b81526004016105f091906138cf565b602060405180830381865afa15801561060b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062f9190613916565b94505050505092915050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061070557507fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061076d57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107d557507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60605f6108366108316040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061082c610827876126d1565b612637565b61267f565b6127e9565b90505f61088061087b6040518060400160405280600a81526020017f746f6b656e5f696e666f000000000000000000000000000000000000000000008152508461267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b81526004016108e092919061379b565b5f60405180830381865afa1580156108fa573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610922919061383e565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5826040518263ffffffff1660e01b815260040161097e919061398b565b5f60405180830381865afa158015610998573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906109c0919061383e565b9350505050919050565b5f805f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d2960056040518060600160405280602c815260200161435d602c91396040518363ffffffff1660e01b8152600401610a4292919061379b565b5f60405180830381865afa158015610a5c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610a84919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401610ae19190613a08565b5f60405180830381865afa158015610afb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610b23919061383e565b90507f6273151f959616268004b58dbb21e5c851b7b8d04498b4aabee12291d22fc034818051906020012014610b8e576040517f438c4bcb000000000000000000000000000000000000000000000000000000008152600401610b8590613a85565b60405180910390fd5b5f610bde6040518060400160405280600881526020017f746f6b656e5f6964000000000000000000000000000000000000000000000000815250610bd9610bd48a6126d1565b612637565b61267f565b90505f610c306040518060400160405280600a81526020017f73616c655f707269636500000000000000000000000000000000000000000000815250610c2b610c268a6126d1565b612637565b61267f565b90505f610cc1610cbc6040518060400160405280600c81526020017f726f79616c74795f696e666f0000000000000000000000000000000000000000815250610cb7610cb287876040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525061279b565b6127e9565b61267f565b6127e9565b90505f610d51610d4c6040518060400160405280600981526020017f657874656e73696f6e0000000000000000000000000000000000000000000000815250610d47610d426040518060400160405280600381526020017f6d736700000000000000000000000000000000000000000000000000000000008152508761267f565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401610db192919061379b565b5f60405180830381865afa158015610dcb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610df3919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401610e509190613aed565b5f60405180830381865afa158015610e6a573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610e92919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982846040518263ffffffff1660e01b8152600401610eef9190613b6a565b602060405180830381865afa158015610f0a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2e9190613916565b90505f825103610f4c575f819a509a50505050505050505050610ff4565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631778e539836040518263ffffffff1660e01b8152600401610fa69190612d52565b602060405180830381865afa158015610fc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe59190613bb1565b819a509a505050505050505050505b9250929050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090613c4c565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806110a957506110a88533611bfb565b5b6110e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110df90613cda565b60405180910390fd5b815183511461112c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112390613d68565b60405180910390fd5b5f5b83518110156111c45782818151811061114a57611149613d86565b5b60200260200101516111768786848151811061116957611168613d86565b5b60200260200101516102bd565b10156111b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ae90613e23565b60405180910390fd5b808060010191505061112e565b505f6112a86040518060400160405280600481526020017f66726f6d000000000000000000000000000000000000000000000000000000008152506112a360085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b815260040161125c919061355b565b5f60405180830381865afa158015611276573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061129e9190613612565b612637565b61267f565b90505f61138d6040518060400160405280600281526020017f746f00000000000000000000000000000000000000000000000000000000000081525061138860085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b8152600401611341919061355b565b5f60405180830381865afa15801561135b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906113839190613612565b612637565b61267f565b90505f6114046040518060400160405280600c81526020017f746f6b656e5f616d6f756e7400000000000000000000000000000000000000008152506040518060400160405280600181526020017f5b0000000000000000000000000000000000000000000000000000000000000081525061267f565b90505f5b8651811015611562575f61147b6040518060400160405280600881526020017f746f6b656e5f69640000000000000000000000000000000000000000000000008152506114766114718b868151811061146457611463613d86565b5b60200260200101516126d1565b612637565b61267f565b90505f6114e76040518060400160405280600681526020017f616d6f756e7400000000000000000000000000000000000000000000000000008152506114e26114dd8b87815181106114d0576114cf613d86565b5b60200260200101516126d1565b612637565b61267f565b90508361153261152d846040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508561279b565b6127e9565b604051602001611543929190613e7b565b6040516020818303038152906040525050508080600101915050611408565b50806040516020016115749190613ec4565b604051602081830303815290604052505f61165261164d6040518060400160405280600a81526020017f73656e645f626174636800000000000000000000000000000000000000000000815250611648611643886040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525061163e8a6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508b61279b565b61279b565b6127e9565b61267f565b6127e9565b905061165d81612831565b508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8a8a6040516116d4929190613ee9565b60405180910390a45f8873ffffffffffffffffffffffffffffffffffffffff163b11156118035763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168873ffffffffffffffffffffffffffffffffffffffff1663bc197c81338c8b8b8b6040518663ffffffff1660e01b8152600401611763959493929190613f1e565b6020604051808303815f875af115801561177f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117a39190613f98565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f99061400d565b60405180910390fd5b5b505050505050505050565b6060815183511461185a57815183516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161185192919061402b565b60405180910390fd5b825167ffffffffffffffff81111561187557611874612dea565b5b6040519080825280602002602001820160405280156118a35781602001602082028036833780820191505090505b5090505f5b835181101561191b576118ef8482815181106118c7576118c6613d86565b5b60200260200101518483815181106118e2576118e1613d86565b5b60200260200101516102bd565b82828151811061190257611901613d86565b5b60200260200101818152505080806001019150506118a8565b5092915050565b5f611a0d611a086040518060400160405280600881526020017f6f70657261746f72000000000000000000000000000000000000000000000000815250611a0360085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016119bc919061355b565b5f60405180830381865afa1580156119d6573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906119fe9190613612565b612637565b61267f565b6127e9565b90508115611a6a57611a64611a5f611a5a6040518060400160405280600b81526020017f617070726f76655f616c6c0000000000000000000000000000000000000000008152508461267f565b6127e9565b612831565b50611abb565b611ab9611ab4611aaf6040518060400160405280600a81526020017f7265766f6b655f616c6c000000000000000000000000000000000000000000008152508461267f565b6127e9565b612831565b505b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611b189190612c9e565b60405180910390a3505050565b60058054611b3290613686565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5e90613686565b8015611ba95780601f10611b8057610100808354040283529160200191611ba9565b820191905f5260205f20905b815481529060010190602001808311611b8c57829003601f168201915b505050505081565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f80611cdf6040518060400160405280600581526020017f6f776e6572000000000000000000000000000000000000000000000000000000815250611cda60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b8152600401611c93919061355b565b5f60405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611cd59190613612565b612637565b61267f565b90505f611dc46040518060400160405280600881526020017f6f70657261746f72000000000000000000000000000000000000000000000000815250611dbf60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b8152600401611d78919061355b565b5f60405180830381865afa158015611d92573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dba9190613612565b612637565b61267f565b90505f611e55611e506040518060400160405280601381526020017f69735f617070726f7665645f666f725f616c6c00000000000000000000000000815250611e4b611e46876040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508861279b565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401611eb592919061379b565b5f60405180830381865afa158015611ecf573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ef7919061383e565b9050600160075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982836040518263ffffffff1660e01b8152600401611f55919061409c565b602060405180830381865afa158015611f70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f949190613916565b1494505050505092915050565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612034576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202b90613c4c565b60405180910390fd5b8161203f86856102bd565b1015612080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207790613e23565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120c057506120bf8533611bfb565b5b6120ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f690613cda565b60405180910390fd5b5f6121e26040518060400160405280600481526020017f66726f6d000000000000000000000000000000000000000000000000000000008152506121dd60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b8152600401612196919061355b565b5f60405180830381865afa1580156121b0573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906121d89190613612565b612637565b61267f565b90505f6122c76040518060400160405280600281526020017f746f0000000000000000000000000000000000000000000000000000000000008152506122c260085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b815260040161227b919061355b565b5f60405180830381865afa158015612295573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122bd9190613612565b612637565b61267f565b90505f6123196040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061231461230f896126d1565b612637565b61267f565b90505f61236b6040518060400160405280600681526020017f616d6f756e740000000000000000000000000000000000000000000000000000815250612366612361896126d1565b612637565b61267f565b90505f61247a6124756040518060400160405280600481526020017f73656e640000000000000000000000000000000000000000000000000000000081525061247061246b896040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506124668b6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506124618d6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508e61279b565b61279b565b61279b565b6127e9565b61267f565b6127e9565b905061248581612831565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b8b6040516124fc92919061402b565b60405180910390a45f8973ffffffffffffffffffffffffffffffffffffffff163b111561262b5763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168973ffffffffffffffffffffffffffffffffffffffff1663f23a6e61338d8c8c8c6040518663ffffffff1660e01b815260040161258b9594939291906140cf565b6020604051808303815f875af11580156125a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125cb9190613f98565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461262a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126219061400d565b60405180910390fd5b5b50505050505050505050565b60608160405160200161264a919061414d565b6040516020818303038152906040526040516020016126699190614172565b6040516020818303038152906040529050919050565b60606126c961268d84612637565b6040518060400160405280600181526020017f3a000000000000000000000000000000000000000000000000000000000000008152508461279b565b905092915050565b60605f60016126df846129af565b0190505f8167ffffffffffffffff8111156126fd576126fc612dea565b5b6040519080825280601f01601f19166020018201604052801561272f5781602001600182028036833780820191505090505b5090505f82602001820190505b600115612790578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161278557612784614197565b5b0494505f850361273c575b819350505050919050565b60608383836040516020016127b1929190613e7b565b6040516020818303038152906040526040516020016127d1929190613e7b565b60405160208183030381529060405290509392505050565b6060816040516020016127fc91906141ea565b60405160208183030381529060405260405160200161281b9190614235565b6040516020818303038152906040529050919050565b60605f8061100273ffffffffffffffffffffffffffffffffffffffff166005856040518060400160405280600281526020017f5b5d0000000000000000000000000000000000000000000000000000000000008152506040516024016128999392919061425a565b6040516020818303038152906040527f44d227ae000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161292391906142de565b5f60405180830381855af49150503d805f811461295b576040519150601f19603f3d011682016040523d82523d5f602084013e612960565b606091505b5091509150816129a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299c9061433e565b60405180910390fd5b8092505050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a0b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612a0157612a00614197565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612a48576d04ee2d6d415b85acef81000000008381612a3e57612a3d614197565b5b0492506020810190505b662386f26fc100008310612a7757662386f26fc100008381612a6d57612a6c614197565b5b0492506010810190505b6305f5e1008310612aa0576305f5e1008381612a9657612a95614197565b5b0492506008810190505b6127108310612ac5576127108381612abb57612aba614197565b5b0492506004810190505b60648310612ae85760648381612ade57612add614197565b5b0492506002810190505b600a8310612af7576001810190505b80915050919050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612b3a82612b11565b9050919050565b612b4a81612b30565b8114612b54575f80fd5b50565b5f81359050612b6581612b41565b92915050565b5f819050919050565b612b7d81612b6b565b8114612b87575f80fd5b50565b5f81359050612b9881612b74565b92915050565b5f8060408385031215612bb457612bb3612b09565b5b5f612bc185828601612b57565b9250506020612bd285828601612b8a565b9150509250929050565b612be581612b6b565b82525050565b5f602082019050612bfe5f830184612bdc565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612c3881612c04565b8114612c42575f80fd5b50565b5f81359050612c5381612c2f565b92915050565b5f60208284031215612c6e57612c6d612b09565b5b5f612c7b84828501612c45565b91505092915050565b5f8115159050919050565b612c9881612c84565b82525050565b5f602082019050612cb15f830184612c8f565b92915050565b5f60208284031215612ccc57612ccb612b09565b5b5f612cd984828501612b8a565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612d2482612ce2565b612d2e8185612cec565b9350612d3e818560208601612cfc565b612d4781612d0a565b840191505092915050565b5f6020820190508181035f830152612d6a8184612d1a565b905092915050565b5f8060408385031215612d8857612d87612b09565b5b5f612d9585828601612b8a565b9250506020612da685828601612b8a565b9150509250929050565b612db981612b30565b82525050565b5f604082019050612dd25f830185612db0565b612ddf6020830184612bdc565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612e2082612d0a565b810181811067ffffffffffffffff82111715612e3f57612e3e612dea565b5b80604052505050565b5f612e51612b00565b9050612e5d8282612e17565b919050565b5f67ffffffffffffffff821115612e7c57612e7b612dea565b5b602082029050602081019050919050565b5f80fd5b5f612ea3612e9e84612e62565b612e48565b90508083825260208201905060208402830185811115612ec657612ec5612e8d565b5b835b81811015612eef5780612edb8882612b8a565b845260208401935050602081019050612ec8565b5050509392505050565b5f82601f830112612f0d57612f0c612de6565b5b8135612f1d848260208601612e91565b91505092915050565b5f80fd5b5f67ffffffffffffffff821115612f4457612f43612dea565b5b612f4d82612d0a565b9050602081019050919050565b828183375f83830152505050565b5f612f7a612f7584612f2a565b612e48565b905082815260208101848484011115612f9657612f95612f26565b5b612fa1848285612f5a565b509392505050565b5f82601f830112612fbd57612fbc612de6565b5b8135612fcd848260208601612f68565b91505092915050565b5f805f805f60a08688031215612fef57612fee612b09565b5b5f612ffc88828901612b57565b955050602061300d88828901612b57565b945050604086013567ffffffffffffffff81111561302e5761302d612b0d565b5b61303a88828901612ef9565b935050606086013567ffffffffffffffff81111561305b5761305a612b0d565b5b61306788828901612ef9565b925050608086013567ffffffffffffffff81111561308857613087612b0d565b5b61309488828901612fa9565b9150509295509295909350565b5f67ffffffffffffffff8211156130bb576130ba612dea565b5b602082029050602081019050919050565b5f6130de6130d9846130a1565b612e48565b9050808382526020820190506020840283018581111561310157613100612e8d565b5b835b8181101561312a57806131168882612b57565b845260208401935050602081019050613103565b5050509392505050565b5f82601f83011261314857613147612de6565b5b81356131588482602086016130cc565b91505092915050565b5f806040838503121561317757613176612b09565b5b5f83013567ffffffffffffffff81111561319457613193612b0d565b5b6131a085828601613134565b925050602083013567ffffffffffffffff8111156131c1576131c0612b0d565b5b6131cd85828601612ef9565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61320981612b6b565b82525050565b5f61321a8383613200565b60208301905092915050565b5f602082019050919050565b5f61323c826131d7565b61324681856131e1565b9350613251836131f1565b805f5b83811015613281578151613268888261320f565b975061327383613226565b925050600181019050613254565b5085935050505092915050565b5f6020820190508181035f8301526132a68184613232565b905092915050565b6132b781612c84565b81146132c1575f80fd5b50565b5f813590506132d2816132ae565b92915050565b5f80604083850312156132ee576132ed612b09565b5b5f6132fb85828601612b57565b925050602061330c858286016132c4565b9150509250929050565b5f819050919050565b5f61333961333461332f84612b11565b613316565b612b11565b9050919050565b5f61334a8261331f565b9050919050565b5f61335b82613340565b9050919050565b61336b81613351565b82525050565b5f6020820190506133845f830184613362565b92915050565b5f61339482613340565b9050919050565b6133a48161338a565b82525050565b5f6020820190506133bd5f83018461339b565b92915050565b5f80604083850312156133d9576133d8612b09565b5b5f6133e685828601612b57565b92505060206133f785828601612b57565b9150509250929050565b5f61340b82613340565b9050919050565b61341b81613401565b82525050565b5f6020820190506134345f830184613412565b92915050565b5f805f805f60a0868803121561345357613452612b09565b5b5f61346088828901612b57565b955050602061347188828901612b57565b945050604061348288828901612b8a565b935050606061349388828901612b8a565b925050608086013567ffffffffffffffff8111156134b4576134b3612b0d565b5b6134c088828901612fa9565b9150509295509295909350565b7f455243313135353a2063616e6e6f742071756572792062616c616e6365206f665f8201527f207a65726f206164647265737300000000000000000000000000000000000000602082015250565b5f613527602d83612cec565b9150613532826134cd565b604082019050919050565b5f6020820190508181035f8301526135548161351b565b9050919050565b5f60208201905061356e5f830184612db0565b92915050565b5f67ffffffffffffffff82111561358e5761358d612dea565b5b61359782612d0a565b9050602081019050919050565b5f6135b66135b184613574565b612e48565b9050828152602081018484840111156135d2576135d1612f26565b5b6135dd848285612cfc565b509392505050565b5f82601f8301126135f9576135f8612de6565b5b81516136098482602086016135a4565b91505092915050565b5f6020828403121561362757613626612b09565b5b5f82015167ffffffffffffffff81111561364457613643612b0d565b5b613650848285016135e5565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061369d57607f821691505b6020821081036136b0576136af613659565b5b50919050565b5f819050815f5260205f209050919050565b5f81546136d481613686565b6136de8186612cec565b9450600182165f81146136f8576001811461370e57613740565b60ff198316865281151560200286019350613740565b613717856136b6565b5f5b8381101561373857815481890152600182019150602081019050613719565b808801955050505b50505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61376d82613749565b6137778185613753565b9350613787818560208601612cfc565b61379081612d0a565b840191505092915050565b5f6040820190508181035f8301526137b381856136c8565b905081810360208301526137c78184613763565b90509392505050565b5f6137e26137dd84612f2a565b612e48565b9050828152602081018484840111156137fe576137fd612f26565b5b613809848285612cfc565b509392505050565b5f82601f83011261382557613824612de6565b5b81516138358482602086016137d0565b91505092915050565b5f6020828403121561385357613852612b09565b5b5f82015167ffffffffffffffff8111156138705761386f612b0d565b5b61387c84828501613811565b91505092915050565b7f62616c616e6365000000000000000000000000000000000000000000000000005f82015250565b5f6138b9600783612cec565b91506138c482613885565b602082019050919050565b5f6040820190508181035f8301526138e78184613763565b905081810360208301526138fa816138ad565b905092915050565b5f8151905061391081612b74565b92915050565b5f6020828403121561392b5761392a612b09565b5b5f61393884828501613902565b91505092915050565b7f746f6b656e5f75726900000000000000000000000000000000000000000000005f82015250565b5f613975600983612cec565b915061398082613941565b602082019050919050565b5f6040820190508181035f8301526139a38184613763565b905081810360208301526139b681613969565b905092915050565b7f726f79616c74795f7061796d656e7473000000000000000000000000000000005f82015250565b5f6139f2601083612cec565b91506139fd826139be565b602082019050919050565b5f6040820190508181035f830152613a208184613763565b90508181036020830152613a33816139e6565b905092915050565b7f726f79616c74795f696e666f00000000000000000000000000000000000000005f82015250565b5f613a6f600c83612cec565b9150613a7a82613a3b565b602082019050919050565b5f6020820190508181035f830152613a9c81613a63565b9050919050565b7f61646472657373000000000000000000000000000000000000000000000000005f82015250565b5f613ad7600783612cec565b9150613ae282613aa3565b602082019050919050565b5f6040820190508181035f830152613b058184613763565b90508181036020830152613b1881613acb565b905092915050565b7f726f79616c74795f616d6f756e740000000000000000000000000000000000005f82015250565b5f613b54600e83612cec565b9150613b5f82613b20565b602082019050919050565b5f6040820190508181035f830152613b828184613763565b90508181036020830152613b9581613b48565b905092915050565b5f81519050613bab81612b41565b92915050565b5f60208284031215613bc657613bc5612b09565b5b5f613bd384828501613b9d565b91505092915050565b7f455243313135353a207472616e7366657220746f20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c36602583612cec565b9150613c4182613bdc565b604082019050919050565b5f6020820190508181035f830152613c6381613c2a565b9050919050565b7f455243313135353a2063616c6c6572206973206e6f7420617070726f766564205f8201527f746f207472616e73666572000000000000000000000000000000000000000000602082015250565b5f613cc4602b83612cec565b9150613ccf82613c6a565b604082019050919050565b5f6020820190508181035f830152613cf181613cb8565b9050919050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e677468205f8201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b5f613d52602883612cec565b9150613d5d82613cf8565b604082019050919050565b5f6020820190508181035f830152613d7f81613d46565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f455243313135353a20696e73756666696369656e742062616c616e636520666f5f8201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b5f613e0d602a83612cec565b9150613e1882613db3565b604082019050919050565b5f6020820190508181035f830152613e3a81613e01565b9050919050565b5f81905092915050565b5f613e5582612ce2565b613e5f8185613e41565b9350613e6f818560208601612cfc565b80840191505092915050565b5f613e868285613e4b565b9150613e928284613e4b565b91508190509392505050565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b5f613ecf8284613e4b565b9150613eda82613e9e565b60018201915081905092915050565b5f6040820190508181035f830152613f018185613232565b90508181036020830152613f158184613232565b90509392505050565b5f60a082019050613f315f830188612db0565b613f3e6020830187612db0565b8181036040830152613f508186613232565b90508181036060830152613f648185613232565b90508181036080830152613f788184613763565b90509695505050505050565b5f81519050613f9281612c2f565b92915050565b5f60208284031215613fad57613fac612b09565b5b5f613fba84828501613f84565b91505092915050565b7f756e73616665207472616e7366657200000000000000000000000000000000005f82015250565b5f613ff7600f83612cec565b915061400282613fc3565b602082019050919050565b5f6020820190508181035f83015261402481613feb565b9050919050565b5f60408201905061403e5f830185612bdc565b61404b6020830184612bdc565b9392505050565b7f617070726f7665640000000000000000000000000000000000000000000000005f82015250565b5f614086600883612cec565b915061409182614052565b602082019050919050565b5f6040820190508181035f8301526140b48184613763565b905081810360208301526140c78161407a565b905092915050565b5f60a0820190506140e25f830188612db0565b6140ef6020830187612db0565b6140fc6040830186612bdc565b6141096060830185612bdc565b818103608083015261411b8184613763565b90509695505050505050565b7f2200000000000000000000000000000000000000000000000000000000000000815250565b5f6141588284613e4b565b915061416382614127565b60018201915081905092915050565b5f61417c82614127565b60018201915061418c8284613e4b565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f7d00000000000000000000000000000000000000000000000000000000000000815250565b5f6141f58284613e4b565b9150614200826141c4565b60018201915081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000815250565b5f61423f8261420f565b60018201915061424f8284613e4b565b915081905092915050565b5f6060820190508181035f83015261427281866136c8565b905081810360208301526142868185613763565b9050818103604083015261429a8184613763565b9050949350505050565b5f81905092915050565b5f6142b882613749565b6142c281856142a4565b93506142d2818560208601612cfc565b80840191505092915050565b5f6142e982846142ae565b915081905092915050565b7f436f736d5761736d2065786563757465206661696c65640000000000000000005f82015250565b5f614328601783612cec565b9150614333826142f4565b602082019050919050565b5f6020820190508181035f8301526143558161431c565b905091905056fe7b22657874656e73696f6e223a7b226d7367223a7b22636865636b5f726f79616c74696573223a7b7d7d7d7da2646970667358221220e27be5e561a26f5c4861dcfd661cb6009a9133ec93a4e83ca93d1e4fdb68217064736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Context.abi b/x/evm/artifacts/cw1155/Context.abi new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/x/evm/artifacts/cw1155/Context.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Context.bin b/x/evm/artifacts/cw1155/Context.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/ERC1155.abi b/x/evm/artifacts/cw1155/ERC1155.abi new file mode 100644 index 000000000..7ab4ea4d5 --- /dev/null +++ b/x/evm/artifacts/cw1155/ERC1155.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC1155.bin b/x/evm/artifacts/cw1155/ERC1155.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/ERC165.abi b/x/evm/artifacts/cw1155/ERC165.abi new file mode 100644 index 000000000..39a77aa90 --- /dev/null +++ b/x/evm/artifacts/cw1155/ERC165.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC165.bin b/x/evm/artifacts/cw1155/ERC165.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/ERC2981.abi b/x/evm/artifacts/cw1155/ERC2981.abi new file mode 100644 index 000000000..76f03a66d --- /dev/null +++ b/x/evm/artifacts/cw1155/ERC2981.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC2981.bin b/x/evm/artifacts/cw1155/ERC2981.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IAddr.abi b/x/evm/artifacts/cw1155/IAddr.abi new file mode 100644 index 000000000..b9a6de290 --- /dev/null +++ b/x/evm/artifacts/cw1155/IAddr.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"addr","type":"string"}],"name":"getEvmAddr","outputs":[{"internalType":"address","name":"response","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getSeiAddr","outputs":[{"internalType":"string","name":"response","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IAddr.bin b/x/evm/artifacts/cw1155/IAddr.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC1155.abi b/x/evm/artifacts/cw1155/IERC1155.abi new file mode 100644 index 000000000..dec1f92d3 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC1155.abi @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155.bin b/x/evm/artifacts/cw1155/IERC1155.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC1155Errors.abi b/x/evm/artifacts/cw1155/IERC1155Errors.abi new file mode 100644 index 000000000..5a136384c --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC1155Errors.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155Errors.bin b/x/evm/artifacts/cw1155/IERC1155Errors.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi b/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi new file mode 100644 index 000000000..a99dbf1f6 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155MetadataURI.bin b/x/evm/artifacts/cw1155/IERC1155MetadataURI.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC1155Receiver.abi b/x/evm/artifacts/cw1155/IERC1155Receiver.abi new file mode 100644 index 000000000..db6856a26 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC1155Receiver.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155Receiver.bin b/x/evm/artifacts/cw1155/IERC1155Receiver.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC165.abi b/x/evm/artifacts/cw1155/IERC165.abi new file mode 100644 index 000000000..39a77aa90 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC165.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC165.bin b/x/evm/artifacts/cw1155/IERC165.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC20Errors.abi b/x/evm/artifacts/cw1155/IERC20Errors.abi new file mode 100644 index 000000000..fe11adb7e --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC20Errors.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC20Errors.bin b/x/evm/artifacts/cw1155/IERC20Errors.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC2981.abi b/x/evm/artifacts/cw1155/IERC2981.abi new file mode 100644 index 000000000..c78e68d33 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC2981.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC2981.bin b/x/evm/artifacts/cw1155/IERC2981.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IERC721Errors.abi b/x/evm/artifacts/cw1155/IERC721Errors.abi new file mode 100644 index 000000000..fcc8d93f4 --- /dev/null +++ b/x/evm/artifacts/cw1155/IERC721Errors.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC721Errors.bin b/x/evm/artifacts/cw1155/IERC721Errors.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IJson.abi b/x/evm/artifacts/cw1155/IJson.abi new file mode 100644 index 000000000..0170dd5a9 --- /dev/null +++ b/x/evm/artifacts/cw1155/IJson.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsBytes","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsBytesList","outputs":[{"internalType":"bytes[]","name":"response","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsUint256","outputs":[{"internalType":"uint256","name":"response","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IJson.bin b/x/evm/artifacts/cw1155/IJson.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/IWasmd.abi b/x/evm/artifacts/cw1155/IWasmd.abi new file mode 100644 index 000000000..3a28c1053 --- /dev/null +++ b/x/evm/artifacts/cw1155/IWasmd.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"contractAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes","name":"coins","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"codeID","type":"uint64"},{"internalType":"string","name":"admin","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"label","type":"string"},{"internalType":"bytes","name":"coins","type":"bytes"}],"name":"instantiate","outputs":[{"internalType":"string","name":"contractAddr","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractAddress","type":"string"},{"internalType":"bytes","name":"req","type":"bytes"}],"name":"query","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IWasmd.bin b/x/evm/artifacts/cw1155/IWasmd.bin new file mode 100644 index 000000000..e69de29bb diff --git a/x/evm/artifacts/cw1155/Math.abi b/x/evm/artifacts/cw1155/Math.abi new file mode 100644 index 000000000..caed19013 --- /dev/null +++ b/x/evm/artifacts/cw1155/Math.abi @@ -0,0 +1 @@ +[{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Math.bin b/x/evm/artifacts/cw1155/Math.bin new file mode 100644 index 000000000..ed0ede2a1 --- /dev/null +++ b/x/evm/artifacts/cw1155/Math.bin @@ -0,0 +1 @@ +6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea264697066735822122040e67ad417bf803cb57ec01a6e23e4a654ad46bd19a0eb64da359e9e33d8a3f864736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/SignedMath.abi b/x/evm/artifacts/cw1155/SignedMath.abi new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/x/evm/artifacts/cw1155/SignedMath.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/SignedMath.bin b/x/evm/artifacts/cw1155/SignedMath.bin new file mode 100644 index 000000000..de587d5e7 --- /dev/null +++ b/x/evm/artifacts/cw1155/SignedMath.bin @@ -0,0 +1 @@ +6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea2646970667358221220be8599de72a170406c0dc84f1fd2a9d9055c24d09aafb92ae56a191a7f06e1cc64736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/StorageSlot.abi b/x/evm/artifacts/cw1155/StorageSlot.abi new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/x/evm/artifacts/cw1155/StorageSlot.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/StorageSlot.bin b/x/evm/artifacts/cw1155/StorageSlot.bin new file mode 100644 index 000000000..a426372d8 --- /dev/null +++ b/x/evm/artifacts/cw1155/StorageSlot.bin @@ -0,0 +1 @@ +6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea26469706673582212204240083d2e46dd977dc4256a1d208c27412b126dd6f07482d7b7013ce01049ef64736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Strings.abi b/x/evm/artifacts/cw1155/Strings.abi new file mode 100644 index 000000000..62828c7c6 --- /dev/null +++ b/x/evm/artifacts/cw1155/Strings.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Strings.bin b/x/evm/artifacts/cw1155/Strings.bin new file mode 100644 index 000000000..1cf79b77f --- /dev/null +++ b/x/evm/artifacts/cw1155/Strings.bin @@ -0,0 +1 @@ +6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea264697066735822122012bb399de1ae2017819b87d45ecc09f805ac42f23925ee077e1cf2d2aaa5608164736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/cw1155.go b/x/evm/artifacts/cw1155/cw1155.go index c043c67dd..e7afa5b38 100644 --- a/x/evm/artifacts/cw1155/cw1155.go +++ b/x/evm/artifacts/cw1155/cw1155.go @@ -29,7 +29,1154 @@ var ( _ = abi.ConvertType ) -// Cw721MetaData contains all meta data concerning the Cw721 contract. +// Cw1155MetaData contains all meta data concerning the Cw1155 contract. var Cw1155MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"Cw721Address_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC721IncorrectOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC721InsufficientApproval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC721InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC721InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC721InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC721InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC721InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC721NonexistentToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplementedOnCosmwasmContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AddrPrecompile\",\"outputs\":[{\"internalType\":\"contractIAddr\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Cw721Address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"JsonPrecompile\",\"outputs\":[{\"internalType\":\"contractIJson\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WasmdPrecompile\",\"outputs\":[{\"internalType\":\"contractIWasmd\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"Cw1155Address_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplementedOnCosmwasmContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AddrPrecompile\",\"outputs\":[{\"internalType\":\"contractIAddr\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Cw1155Address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"JsonPrecompile\",\"outputs\":[{\"internalType\":\"contractIJson\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WasmdPrecompile\",\"outputs\":[{\"internalType\":\"contractIWasmd\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"balances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// Cw1155ABI is the input ABI used to generate the binding from. +// Deprecated: Use Cw1155MetaData.ABI instead. +var Cw1155ABI = Cw1155MetaData.ABI + +// Cw1155 is an auto generated Go binding around an Ethereum contract. +type Cw1155 struct { + Cw1155Caller // Read-only binding to the contract + Cw1155Transactor // Write-only binding to the contract + Cw1155Filterer // Log filterer for contract events +} + +// Cw1155Caller is an auto generated read-only Go binding around an Ethereum contract. +type Cw1155Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Cw1155Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Cw1155Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Cw1155Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Cw1155Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Cw1155Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Cw1155Session struct { + Contract *Cw1155 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Cw1155CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Cw1155CallerSession struct { + Contract *Cw1155Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Cw1155TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Cw1155TransactorSession struct { + Contract *Cw1155Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Cw1155Raw is an auto generated low-level Go binding around an Ethereum contract. +type Cw1155Raw struct { + Contract *Cw1155 // Generic contract binding to access the raw methods on +} + +// Cw1155CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Cw1155CallerRaw struct { + Contract *Cw1155Caller // Generic read-only contract binding to access the raw methods on +} + +// Cw1155TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Cw1155TransactorRaw struct { + Contract *Cw1155Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewCw1155 creates a new instance of Cw1155, bound to a specific deployed contract. +func NewCw1155(address common.Address, backend bind.ContractBackend) (*Cw1155, error) { + contract, err := bindCw1155(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Cw1155{Cw1155Caller: Cw1155Caller{contract: contract}, Cw1155Transactor: Cw1155Transactor{contract: contract}, Cw1155Filterer: Cw1155Filterer{contract: contract}}, nil +} + +// NewCw1155Caller creates a new read-only instance of Cw1155, bound to a specific deployed contract. +func NewCw1155Caller(address common.Address, caller bind.ContractCaller) (*Cw1155Caller, error) { + contract, err := bindCw1155(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Cw1155Caller{contract: contract}, nil +} + +// NewCw1155Transactor creates a new write-only instance of Cw1155, bound to a specific deployed contract. +func NewCw1155Transactor(address common.Address, transactor bind.ContractTransactor) (*Cw1155Transactor, error) { + contract, err := bindCw1155(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Cw1155Transactor{contract: contract}, nil +} + +// NewCw1155Filterer creates a new log filterer instance of Cw1155, bound to a specific deployed contract. +func NewCw1155Filterer(address common.Address, filterer bind.ContractFilterer) (*Cw1155Filterer, error) { + contract, err := bindCw1155(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Cw1155Filterer{contract: contract}, nil +} + +// bindCw1155 binds a generic wrapper to an already deployed contract. +func bindCw1155(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Cw1155 *Cw1155Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Cw1155.Contract.Cw1155Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Cw1155 *Cw1155Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Cw1155.Contract.Cw1155Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Cw1155 *Cw1155Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Cw1155.Contract.Cw1155Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Cw1155 *Cw1155CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Cw1155.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Cw1155 *Cw1155TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Cw1155.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Cw1155 *Cw1155TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Cw1155.Contract.contract.Transact(opts, method, params...) +} + +// AddrPrecompile is a free data retrieval call binding the contract method 0xc2aed302. +// +// Solidity: function AddrPrecompile() view returns(address) +func (_Cw1155 *Cw1155Caller) AddrPrecompile(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "AddrPrecompile") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// AddrPrecompile is a free data retrieval call binding the contract method 0xc2aed302. +// +// Solidity: function AddrPrecompile() view returns(address) +func (_Cw1155 *Cw1155Session) AddrPrecompile() (common.Address, error) { + return _Cw1155.Contract.AddrPrecompile(&_Cw1155.CallOpts) +} + +// AddrPrecompile is a free data retrieval call binding the contract method 0xc2aed302. +// +// Solidity: function AddrPrecompile() view returns(address) +func (_Cw1155 *Cw1155CallerSession) AddrPrecompile() (common.Address, error) { + return _Cw1155.Contract.AddrPrecompile(&_Cw1155.CallOpts) +} + +// Cw1155Address is a free data retrieval call binding the contract method 0xb98933a0. +// +// Solidity: function Cw1155Address() view returns(string) +func (_Cw1155 *Cw1155Caller) Cw1155Address(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "Cw1155Address") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Cw1155Address is a free data retrieval call binding the contract method 0xb98933a0. +// +// Solidity: function Cw1155Address() view returns(string) +func (_Cw1155 *Cw1155Session) Cw1155Address() (string, error) { + return _Cw1155.Contract.Cw1155Address(&_Cw1155.CallOpts) +} + +// Cw1155Address is a free data retrieval call binding the contract method 0xb98933a0. +// +// Solidity: function Cw1155Address() view returns(string) +func (_Cw1155 *Cw1155CallerSession) Cw1155Address() (string, error) { + return _Cw1155.Contract.Cw1155Address(&_Cw1155.CallOpts) +} + +// JsonPrecompile is a free data retrieval call binding the contract method 0xde4725cc. +// +// Solidity: function JsonPrecompile() view returns(address) +func (_Cw1155 *Cw1155Caller) JsonPrecompile(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "JsonPrecompile") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// JsonPrecompile is a free data retrieval call binding the contract method 0xde4725cc. +// +// Solidity: function JsonPrecompile() view returns(address) +func (_Cw1155 *Cw1155Session) JsonPrecompile() (common.Address, error) { + return _Cw1155.Contract.JsonPrecompile(&_Cw1155.CallOpts) +} + +// JsonPrecompile is a free data retrieval call binding the contract method 0xde4725cc. +// +// Solidity: function JsonPrecompile() view returns(address) +func (_Cw1155 *Cw1155CallerSession) JsonPrecompile() (common.Address, error) { + return _Cw1155.Contract.JsonPrecompile(&_Cw1155.CallOpts) +} + +// WasmdPrecompile is a free data retrieval call binding the contract method 0xf00b0255. +// +// Solidity: function WasmdPrecompile() view returns(address) +func (_Cw1155 *Cw1155Caller) WasmdPrecompile(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "WasmdPrecompile") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WasmdPrecompile is a free data retrieval call binding the contract method 0xf00b0255. +// +// Solidity: function WasmdPrecompile() view returns(address) +func (_Cw1155 *Cw1155Session) WasmdPrecompile() (common.Address, error) { + return _Cw1155.Contract.WasmdPrecompile(&_Cw1155.CallOpts) +} + +// WasmdPrecompile is a free data retrieval call binding the contract method 0xf00b0255. +// +// Solidity: function WasmdPrecompile() view returns(address) +func (_Cw1155 *Cw1155CallerSession) WasmdPrecompile() (common.Address, error) { + return _Cw1155.Contract.WasmdPrecompile(&_Cw1155.CallOpts) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155Caller) BalanceOf(opts *bind.CallOpts, account common.Address, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "balanceOf", account, id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155Session) BalanceOf(account common.Address, id *big.Int) (*big.Int, error) { + return _Cw1155.Contract.BalanceOf(&_Cw1155.CallOpts, account, id) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155CallerSession) BalanceOf(account common.Address, id *big.Int) (*big.Int, error) { + return _Cw1155.Contract.BalanceOf(&_Cw1155.CallOpts, account, id) +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[] balances) +func (_Cw1155 *Cw1155Caller) BalanceOfBatch(opts *bind.CallOpts, accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "balanceOfBatch", accounts, ids) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[] balances) +func (_Cw1155 *Cw1155Session) BalanceOfBatch(accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + return _Cw1155.Contract.BalanceOfBatch(&_Cw1155.CallOpts, accounts, ids) +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[] balances) +func (_Cw1155 *Cw1155CallerSession) BalanceOfBatch(accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + return _Cw1155.Contract.BalanceOfBatch(&_Cw1155.CallOpts, accounts, ids) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_Cw1155 *Cw1155Caller) IsApprovedForAll(opts *bind.CallOpts, owner common.Address, operator common.Address) (bool, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "isApprovedForAll", owner, operator) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_Cw1155 *Cw1155Session) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _Cw1155.Contract.IsApprovedForAll(&_Cw1155.CallOpts, owner, operator) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_Cw1155 *Cw1155CallerSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _Cw1155.Contract.IsApprovedForAll(&_Cw1155.CallOpts, owner, operator) +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Cw1155 *Cw1155Caller) RoyaltyInfo(opts *bind.CallOpts, tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "royaltyInfo", tokenId, salePrice) + + if err != nil { + return *new(common.Address), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return out0, out1, err + +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Cw1155 *Cw1155Session) RoyaltyInfo(tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + return _Cw1155.Contract.RoyaltyInfo(&_Cw1155.CallOpts, tokenId, salePrice) +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Cw1155 *Cw1155CallerSession) RoyaltyInfo(tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + return _Cw1155.Contract.RoyaltyInfo(&_Cw1155.CallOpts, tokenId, salePrice) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) pure returns(bool) +func (_Cw1155 *Cw1155Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) pure returns(bool) +func (_Cw1155 *Cw1155Session) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Cw1155.Contract.SupportsInterface(&_Cw1155.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) pure returns(bool) +func (_Cw1155 *Cw1155CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Cw1155.Contract.SupportsInterface(&_Cw1155.CallOpts, interfaceId) +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 id) view returns(string) +func (_Cw1155 *Cw1155Caller) Uri(opts *bind.CallOpts, id *big.Int) (string, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "uri", id) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 id) view returns(string) +func (_Cw1155 *Cw1155Session) Uri(id *big.Int) (string, error) { + return _Cw1155.Contract.Uri(&_Cw1155.CallOpts, id) +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 id) view returns(string) +func (_Cw1155 *Cw1155CallerSession) Uri(id *big.Int) (string, error) { + return _Cw1155.Contract.Uri(&_Cw1155.CallOpts, id) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) returns() +func (_Cw1155 *Cw1155Transactor) SafeBatchTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, ids []*big.Int, amounts []*big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.contract.Transact(opts, "safeBatchTransferFrom", from, to, ids, amounts, data) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) returns() +func (_Cw1155 *Cw1155Session) SafeBatchTransferFrom(from common.Address, to common.Address, ids []*big.Int, amounts []*big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.Contract.SafeBatchTransferFrom(&_Cw1155.TransactOpts, from, to, ids, amounts, data) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) returns() +func (_Cw1155 *Cw1155TransactorSession) SafeBatchTransferFrom(from common.Address, to common.Address, ids []*big.Int, amounts []*big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.Contract.SafeBatchTransferFrom(&_Cw1155.TransactOpts, from, to, ids, amounts, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) returns() +func (_Cw1155 *Cw1155Transactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, id *big.Int, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.contract.Transact(opts, "safeTransferFrom", from, to, id, amount, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) returns() +func (_Cw1155 *Cw1155Session) SafeTransferFrom(from common.Address, to common.Address, id *big.Int, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.Contract.SafeTransferFrom(&_Cw1155.TransactOpts, from, to, id, amount, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) returns() +func (_Cw1155 *Cw1155TransactorSession) SafeTransferFrom(from common.Address, to common.Address, id *big.Int, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Cw1155.Contract.SafeTransferFrom(&_Cw1155.TransactOpts, from, to, id, amount, data) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Cw1155 *Cw1155Transactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, approved bool) (*types.Transaction, error) { + return _Cw1155.contract.Transact(opts, "setApprovalForAll", operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Cw1155 *Cw1155Session) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _Cw1155.Contract.SetApprovalForAll(&_Cw1155.TransactOpts, operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Cw1155 *Cw1155TransactorSession) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _Cw1155.Contract.SetApprovalForAll(&_Cw1155.TransactOpts, operator, approved) +} + +// Cw1155ApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the Cw1155 contract. +type Cw1155ApprovalForAllIterator struct { + Event *Cw1155ApprovalForAll // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Cw1155ApprovalForAllIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Cw1155ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Cw1155ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Cw1155ApprovalForAllIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Cw1155ApprovalForAllIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Cw1155ApprovalForAll represents a ApprovalForAll event raised by the Cw1155 contract. +type Cw1155ApprovalForAll struct { + Account common.Address + Operator common.Address + Approved bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Cw1155 *Cw1155Filterer) FilterApprovalForAll(opts *bind.FilterOpts, account []common.Address, operator []common.Address) (*Cw1155ApprovalForAllIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _Cw1155.contract.FilterLogs(opts, "ApprovalForAll", accountRule, operatorRule) + if err != nil { + return nil, err + } + return &Cw1155ApprovalForAllIterator{contract: _Cw1155.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil +} + +// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Cw1155 *Cw1155Filterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *Cw1155ApprovalForAll, account []common.Address, operator []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _Cw1155.contract.WatchLogs(opts, "ApprovalForAll", accountRule, operatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Cw1155ApprovalForAll) + if err := _Cw1155.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Cw1155 *Cw1155Filterer) ParseApprovalForAll(log types.Log) (*Cw1155ApprovalForAll, error) { + event := new(Cw1155ApprovalForAll) + if err := _Cw1155.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Cw1155TransferBatchIterator is returned from FilterTransferBatch and is used to iterate over the raw logs and unpacked data for TransferBatch events raised by the Cw1155 contract. +type Cw1155TransferBatchIterator struct { + Event *Cw1155TransferBatch // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Cw1155TransferBatchIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Cw1155TransferBatch) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Cw1155TransferBatch) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Cw1155TransferBatchIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Cw1155TransferBatchIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Cw1155TransferBatch represents a TransferBatch event raised by the Cw1155 contract. +type Cw1155TransferBatch struct { + Operator common.Address + From common.Address + To common.Address + Ids []*big.Int + Values []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransferBatch is a free log retrieval operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Cw1155 *Cw1155Filterer) FilterTransferBatch(opts *bind.FilterOpts, operator []common.Address, from []common.Address, to []common.Address) (*Cw1155TransferBatchIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Cw1155.contract.FilterLogs(opts, "TransferBatch", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &Cw1155TransferBatchIterator{contract: _Cw1155.contract, event: "TransferBatch", logs: logs, sub: sub}, nil +} + +// WatchTransferBatch is a free log subscription operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Cw1155 *Cw1155Filterer) WatchTransferBatch(opts *bind.WatchOpts, sink chan<- *Cw1155TransferBatch, operator []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Cw1155.contract.WatchLogs(opts, "TransferBatch", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Cw1155TransferBatch) + if err := _Cw1155.contract.UnpackLog(event, "TransferBatch", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransferBatch is a log parse operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Cw1155 *Cw1155Filterer) ParseTransferBatch(log types.Log) (*Cw1155TransferBatch, error) { + event := new(Cw1155TransferBatch) + if err := _Cw1155.contract.UnpackLog(event, "TransferBatch", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Cw1155TransferSingleIterator is returned from FilterTransferSingle and is used to iterate over the raw logs and unpacked data for TransferSingle events raised by the Cw1155 contract. +type Cw1155TransferSingleIterator struct { + Event *Cw1155TransferSingle // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Cw1155TransferSingleIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Cw1155TransferSingle) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Cw1155TransferSingle) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Cw1155TransferSingleIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Cw1155TransferSingleIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Cw1155TransferSingle represents a TransferSingle event raised by the Cw1155 contract. +type Cw1155TransferSingle struct { + Operator common.Address + From common.Address + To common.Address + Id *big.Int + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransferSingle is a free log retrieval operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Cw1155 *Cw1155Filterer) FilterTransferSingle(opts *bind.FilterOpts, operator []common.Address, from []common.Address, to []common.Address) (*Cw1155TransferSingleIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Cw1155.contract.FilterLogs(opts, "TransferSingle", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &Cw1155TransferSingleIterator{contract: _Cw1155.contract, event: "TransferSingle", logs: logs, sub: sub}, nil +} + +// WatchTransferSingle is a free log subscription operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Cw1155 *Cw1155Filterer) WatchTransferSingle(opts *bind.WatchOpts, sink chan<- *Cw1155TransferSingle, operator []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Cw1155.contract.WatchLogs(opts, "TransferSingle", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Cw1155TransferSingle) + if err := _Cw1155.contract.UnpackLog(event, "TransferSingle", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransferSingle is a log parse operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Cw1155 *Cw1155Filterer) ParseTransferSingle(log types.Log) (*Cw1155TransferSingle, error) { + event := new(Cw1155TransferSingle) + if err := _Cw1155.contract.UnpackLog(event, "TransferSingle", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Cw1155URIIterator is returned from FilterURI and is used to iterate over the raw logs and unpacked data for URI events raised by the Cw1155 contract. +type Cw1155URIIterator struct { + Event *Cw1155URI // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Cw1155URIIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Cw1155URI) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Cw1155URI) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Cw1155URIIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Cw1155URIIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Cw1155URI represents a URI event raised by the Cw1155 contract. +type Cw1155URI struct { + Value string + Id *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterURI is a free log retrieval operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Cw1155 *Cw1155Filterer) FilterURI(opts *bind.FilterOpts, id []*big.Int) (*Cw1155URIIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _Cw1155.contract.FilterLogs(opts, "URI", idRule) + if err != nil { + return nil, err + } + return &Cw1155URIIterator{contract: _Cw1155.contract, event: "URI", logs: logs, sub: sub}, nil +} + +// WatchURI is a free log subscription operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Cw1155 *Cw1155Filterer) WatchURI(opts *bind.WatchOpts, sink chan<- *Cw1155URI, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _Cw1155.contract.WatchLogs(opts, "URI", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Cw1155URI) + if err := _Cw1155.contract.UnpackLog(event, "URI", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseURI is a log parse operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Cw1155 *Cw1155Filterer) ParseURI(log types.Log) (*Cw1155URI, error) { + event := new(Cw1155URI) + if err := _Cw1155.contract.UnpackLog(event, "URI", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } From b117fb265e9bee1ac95f8f4e3ef52a9d0f10fb23 Mon Sep 17 00:00:00 2001 From: Mr Meat <77750450+mr-meat@users.noreply.github.com> Date: Wed, 26 Jun 2024 01:13:01 +0100 Subject: [PATCH 21/65] clean up unused artifacts --- x/evm/artifacts/cw1155/Arrays.abi | 1 - x/evm/artifacts/cw1155/Arrays.bin | 1 - x/evm/artifacts/cw1155/Context.abi | 1 - x/evm/artifacts/cw1155/Context.bin | 0 x/evm/artifacts/cw1155/ERC1155.abi | 1 - x/evm/artifacts/cw1155/ERC1155.bin | 0 x/evm/artifacts/cw1155/ERC165.abi | 1 - x/evm/artifacts/cw1155/ERC165.bin | 0 x/evm/artifacts/cw1155/ERC2981.abi | 1 - x/evm/artifacts/cw1155/ERC2981.bin | 0 x/evm/artifacts/cw1155/IAddr.abi | 1 - x/evm/artifacts/cw1155/IAddr.bin | 0 x/evm/artifacts/cw1155/IERC1155.abi | 1 - x/evm/artifacts/cw1155/IERC1155.bin | 0 x/evm/artifacts/cw1155/IERC1155Errors.abi | 1 - x/evm/artifacts/cw1155/IERC1155Errors.bin | 0 x/evm/artifacts/cw1155/IERC1155MetadataURI.abi | 1 - x/evm/artifacts/cw1155/IERC1155MetadataURI.bin | 0 x/evm/artifacts/cw1155/IERC1155Receiver.abi | 1 - x/evm/artifacts/cw1155/IERC1155Receiver.bin | 0 x/evm/artifacts/cw1155/IERC165.abi | 1 - x/evm/artifacts/cw1155/IERC165.bin | 0 x/evm/artifacts/cw1155/IERC20Errors.abi | 1 - x/evm/artifacts/cw1155/IERC20Errors.bin | 0 x/evm/artifacts/cw1155/IERC2981.abi | 1 - x/evm/artifacts/cw1155/IERC2981.bin | 0 x/evm/artifacts/cw1155/IERC721Errors.abi | 1 - x/evm/artifacts/cw1155/IERC721Errors.bin | 0 x/evm/artifacts/cw1155/IJson.abi | 1 - x/evm/artifacts/cw1155/IJson.bin | 0 x/evm/artifacts/cw1155/IWasmd.abi | 1 - x/evm/artifacts/cw1155/IWasmd.bin | 0 x/evm/artifacts/cw1155/Math.abi | 1 - x/evm/artifacts/cw1155/Math.bin | 1 - x/evm/artifacts/cw1155/SignedMath.abi | 1 - x/evm/artifacts/cw1155/SignedMath.bin | 1 - x/evm/artifacts/cw1155/StorageSlot.abi | 1 - x/evm/artifacts/cw1155/StorageSlot.bin | 1 - x/evm/artifacts/cw1155/Strings.abi | 1 - x/evm/artifacts/cw1155/Strings.bin | 1 - 40 files changed, 25 deletions(-) delete mode 100644 x/evm/artifacts/cw1155/Arrays.abi delete mode 100644 x/evm/artifacts/cw1155/Arrays.bin delete mode 100644 x/evm/artifacts/cw1155/Context.abi delete mode 100644 x/evm/artifacts/cw1155/Context.bin delete mode 100644 x/evm/artifacts/cw1155/ERC1155.abi delete mode 100644 x/evm/artifacts/cw1155/ERC1155.bin delete mode 100644 x/evm/artifacts/cw1155/ERC165.abi delete mode 100644 x/evm/artifacts/cw1155/ERC165.bin delete mode 100644 x/evm/artifacts/cw1155/ERC2981.abi delete mode 100644 x/evm/artifacts/cw1155/ERC2981.bin delete mode 100644 x/evm/artifacts/cw1155/IAddr.abi delete mode 100644 x/evm/artifacts/cw1155/IAddr.bin delete mode 100644 x/evm/artifacts/cw1155/IERC1155.abi delete mode 100644 x/evm/artifacts/cw1155/IERC1155.bin delete mode 100644 x/evm/artifacts/cw1155/IERC1155Errors.abi delete mode 100644 x/evm/artifacts/cw1155/IERC1155Errors.bin delete mode 100644 x/evm/artifacts/cw1155/IERC1155MetadataURI.abi delete mode 100644 x/evm/artifacts/cw1155/IERC1155MetadataURI.bin delete mode 100644 x/evm/artifacts/cw1155/IERC1155Receiver.abi delete mode 100644 x/evm/artifacts/cw1155/IERC1155Receiver.bin delete mode 100644 x/evm/artifacts/cw1155/IERC165.abi delete mode 100644 x/evm/artifacts/cw1155/IERC165.bin delete mode 100644 x/evm/artifacts/cw1155/IERC20Errors.abi delete mode 100644 x/evm/artifacts/cw1155/IERC20Errors.bin delete mode 100644 x/evm/artifacts/cw1155/IERC2981.abi delete mode 100644 x/evm/artifacts/cw1155/IERC2981.bin delete mode 100644 x/evm/artifacts/cw1155/IERC721Errors.abi delete mode 100644 x/evm/artifacts/cw1155/IERC721Errors.bin delete mode 100644 x/evm/artifacts/cw1155/IJson.abi delete mode 100644 x/evm/artifacts/cw1155/IJson.bin delete mode 100644 x/evm/artifacts/cw1155/IWasmd.abi delete mode 100644 x/evm/artifacts/cw1155/IWasmd.bin delete mode 100644 x/evm/artifacts/cw1155/Math.abi delete mode 100644 x/evm/artifacts/cw1155/Math.bin delete mode 100644 x/evm/artifacts/cw1155/SignedMath.abi delete mode 100644 x/evm/artifacts/cw1155/SignedMath.bin delete mode 100644 x/evm/artifacts/cw1155/StorageSlot.abi delete mode 100644 x/evm/artifacts/cw1155/StorageSlot.bin delete mode 100644 x/evm/artifacts/cw1155/Strings.abi delete mode 100644 x/evm/artifacts/cw1155/Strings.bin diff --git a/x/evm/artifacts/cw1155/Arrays.abi b/x/evm/artifacts/cw1155/Arrays.abi deleted file mode 100644 index 0637a088a..000000000 --- a/x/evm/artifacts/cw1155/Arrays.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Arrays.bin b/x/evm/artifacts/cw1155/Arrays.bin deleted file mode 100644 index 15ba16e72..000000000 --- a/x/evm/artifacts/cw1155/Arrays.bin +++ /dev/null @@ -1 +0,0 @@ -6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea26469706673582212201aad5655fee17ba323abb11a28d38fccb4e505a23222c48e002b0b021e21522964736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Context.abi b/x/evm/artifacts/cw1155/Context.abi deleted file mode 100644 index 0637a088a..000000000 --- a/x/evm/artifacts/cw1155/Context.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Context.bin b/x/evm/artifacts/cw1155/Context.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/ERC1155.abi b/x/evm/artifacts/cw1155/ERC1155.abi deleted file mode 100644 index 7ab4ea4d5..000000000 --- a/x/evm/artifacts/cw1155/ERC1155.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC1155.bin b/x/evm/artifacts/cw1155/ERC1155.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/ERC165.abi b/x/evm/artifacts/cw1155/ERC165.abi deleted file mode 100644 index 39a77aa90..000000000 --- a/x/evm/artifacts/cw1155/ERC165.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC165.bin b/x/evm/artifacts/cw1155/ERC165.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/ERC2981.abi b/x/evm/artifacts/cw1155/ERC2981.abi deleted file mode 100644 index 76f03a66d..000000000 --- a/x/evm/artifacts/cw1155/ERC2981.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/ERC2981.bin b/x/evm/artifacts/cw1155/ERC2981.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IAddr.abi b/x/evm/artifacts/cw1155/IAddr.abi deleted file mode 100644 index b9a6de290..000000000 --- a/x/evm/artifacts/cw1155/IAddr.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"string","name":"addr","type":"string"}],"name":"getEvmAddr","outputs":[{"internalType":"address","name":"response","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getSeiAddr","outputs":[{"internalType":"string","name":"response","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IAddr.bin b/x/evm/artifacts/cw1155/IAddr.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC1155.abi b/x/evm/artifacts/cw1155/IERC1155.abi deleted file mode 100644 index dec1f92d3..000000000 --- a/x/evm/artifacts/cw1155/IERC1155.abi +++ /dev/null @@ -1 +0,0 @@ -[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155.bin b/x/evm/artifacts/cw1155/IERC1155.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC1155Errors.abi b/x/evm/artifacts/cw1155/IERC1155Errors.abi deleted file mode 100644 index 5a136384c..000000000 --- a/x/evm/artifacts/cw1155/IERC1155Errors.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155Errors.bin b/x/evm/artifacts/cw1155/IERC1155Errors.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi b/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi deleted file mode 100644 index a99dbf1f6..000000000 --- a/x/evm/artifacts/cw1155/IERC1155MetadataURI.abi +++ /dev/null @@ -1 +0,0 @@ -[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155MetadataURI.bin b/x/evm/artifacts/cw1155/IERC1155MetadataURI.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC1155Receiver.abi b/x/evm/artifacts/cw1155/IERC1155Receiver.abi deleted file mode 100644 index db6856a26..000000000 --- a/x/evm/artifacts/cw1155/IERC1155Receiver.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC1155Receiver.bin b/x/evm/artifacts/cw1155/IERC1155Receiver.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC165.abi b/x/evm/artifacts/cw1155/IERC165.abi deleted file mode 100644 index 39a77aa90..000000000 --- a/x/evm/artifacts/cw1155/IERC165.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC165.bin b/x/evm/artifacts/cw1155/IERC165.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC20Errors.abi b/x/evm/artifacts/cw1155/IERC20Errors.abi deleted file mode 100644 index fe11adb7e..000000000 --- a/x/evm/artifacts/cw1155/IERC20Errors.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC20Errors.bin b/x/evm/artifacts/cw1155/IERC20Errors.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC2981.abi b/x/evm/artifacts/cw1155/IERC2981.abi deleted file mode 100644 index c78e68d33..000000000 --- a/x/evm/artifacts/cw1155/IERC2981.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC2981.bin b/x/evm/artifacts/cw1155/IERC2981.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IERC721Errors.abi b/x/evm/artifacts/cw1155/IERC721Errors.abi deleted file mode 100644 index fcc8d93f4..000000000 --- a/x/evm/artifacts/cw1155/IERC721Errors.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IERC721Errors.bin b/x/evm/artifacts/cw1155/IERC721Errors.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IJson.abi b/x/evm/artifacts/cw1155/IJson.abi deleted file mode 100644 index 0170dd5a9..000000000 --- a/x/evm/artifacts/cw1155/IJson.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsBytes","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsBytesList","outputs":[{"internalType":"bytes[]","name":"response","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"string","name":"key","type":"string"}],"name":"extractAsUint256","outputs":[{"internalType":"uint256","name":"response","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IJson.bin b/x/evm/artifacts/cw1155/IJson.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/IWasmd.abi b/x/evm/artifacts/cw1155/IWasmd.abi deleted file mode 100644 index 3a28c1053..000000000 --- a/x/evm/artifacts/cw1155/IWasmd.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"string","name":"contractAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes","name":"coins","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"codeID","type":"uint64"},{"internalType":"string","name":"admin","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"label","type":"string"},{"internalType":"bytes","name":"coins","type":"bytes"}],"name":"instantiate","outputs":[{"internalType":"string","name":"contractAddr","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractAddress","type":"string"},{"internalType":"bytes","name":"req","type":"bytes"}],"name":"query","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/IWasmd.bin b/x/evm/artifacts/cw1155/IWasmd.bin deleted file mode 100644 index e69de29bb..000000000 diff --git a/x/evm/artifacts/cw1155/Math.abi b/x/evm/artifacts/cw1155/Math.abi deleted file mode 100644 index caed19013..000000000 --- a/x/evm/artifacts/cw1155/Math.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Math.bin b/x/evm/artifacts/cw1155/Math.bin deleted file mode 100644 index ed0ede2a1..000000000 --- a/x/evm/artifacts/cw1155/Math.bin +++ /dev/null @@ -1 +0,0 @@ -6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea264697066735822122040e67ad417bf803cb57ec01a6e23e4a654ad46bd19a0eb64da359e9e33d8a3f864736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/SignedMath.abi b/x/evm/artifacts/cw1155/SignedMath.abi deleted file mode 100644 index 0637a088a..000000000 --- a/x/evm/artifacts/cw1155/SignedMath.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/SignedMath.bin b/x/evm/artifacts/cw1155/SignedMath.bin deleted file mode 100644 index de587d5e7..000000000 --- a/x/evm/artifacts/cw1155/SignedMath.bin +++ /dev/null @@ -1 +0,0 @@ -6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea2646970667358221220be8599de72a170406c0dc84f1fd2a9d9055c24d09aafb92ae56a191a7f06e1cc64736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/StorageSlot.abi b/x/evm/artifacts/cw1155/StorageSlot.abi deleted file mode 100644 index 0637a088a..000000000 --- a/x/evm/artifacts/cw1155/StorageSlot.abi +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/StorageSlot.bin b/x/evm/artifacts/cw1155/StorageSlot.bin deleted file mode 100644 index a426372d8..000000000 --- a/x/evm/artifacts/cw1155/StorageSlot.bin +++ /dev/null @@ -1 +0,0 @@ -6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea26469706673582212204240083d2e46dd977dc4256a1d208c27412b126dd6f07482d7b7013ce01049ef64736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Strings.abi b/x/evm/artifacts/cw1155/Strings.abi deleted file mode 100644 index 62828c7c6..000000000 --- a/x/evm/artifacts/cw1155/Strings.abi +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/Strings.bin b/x/evm/artifacts/cw1155/Strings.bin deleted file mode 100644 index 1cf79b77f..000000000 --- a/x/evm/artifacts/cw1155/Strings.bin +++ /dev/null @@ -1 +0,0 @@ -6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea264697066735822122012bb399de1ae2017819b87d45ecc09f805ac42f23925ee077e1cf2d2aaa5608164736f6c63430008190033 \ No newline at end of file From 68ed5a0b5512adb5c6e3ac38204fa74351f4cbc4 Mon Sep 17 00:00:00 2001 From: davyli Date: Sun, 30 Jun 2024 18:02:16 -0400 Subject: [PATCH 22/65] Add all go bindings --- contracts/src/CW1155ERC1155Pointer.sol | 28 +- ...t.t.sol => CW1155ERC1155PointerTest.t.sol} | 2 +- example/contracts/erc1155/ERC1155Example.abi | 1 + example/contracts/erc1155/ERC1155Example.bin | 1 + example/contracts/erc1155/ERC1155Example.sol | 60 + example/contracts/erc1155/erc1155.go | 1234 +++++++++++++++++ example/contracts/erc721/README.md | 2 +- wasmbinding/queries.go | 33 + .../artifacts/cw1155/CW1155ERC1155Pointer.abi | 2 +- .../artifacts/cw1155/CW1155ERC1155Pointer.bin | 2 +- x/evm/artifacts/cw1155/artifacts.go | 10 +- x/evm/artifacts/cw1155/cw1155.go | 157 ++- x/evm/client/wasm/bindings/queries.go | 203 ++- x/evm/client/wasm/query.go | 428 +++++- x/evm/client/wasm/query_test.go | 190 ++- 15 files changed, 2306 insertions(+), 47 deletions(-) rename contracts/test/{CW1155toERC1155PointerTest.t.sol => CW1155ERC1155PointerTest.t.sol} (99%) create mode 100644 example/contracts/erc1155/ERC1155Example.abi create mode 100644 example/contracts/erc1155/ERC1155Example.bin create mode 100644 example/contracts/erc1155/ERC1155Example.sol create mode 100644 example/contracts/erc1155/erc1155.go diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index c8d576c0c..3f2359805 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -15,7 +15,6 @@ import {IAddr} from "./precompiles/IAddr.sol"; contract CW1155ERC1155Pointer is ERC1155, ERC2981 { - address constant WASMD_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001002; address constant JSON_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001003; address constant ADDR_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000001004; @@ -24,15 +23,19 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { IWasmd public WasmdPrecompile; IJson public JsonPrecompile; IAddr public AddrPrecompile; + string public name; + string public symbol; error NotImplementedOnCosmwasmContract(string method); error NotImplemented(string method); - constructor(string memory Cw1155Address_, string memory uri_) ERC1155(uri_) { + constructor(string memory Cw1155Address_, string memory name_, string memory symbol_) ERC1155("") { + Cw1155Address = Cw1155Address_; WasmdPrecompile = IWasmd(WASMD_PRECOMPILE_ADDRESS); JsonPrecompile = IJson(JSON_PRECOMPILE_ADDRESS); AddrPrecompile = IAddr(ADDR_PRECOMPILE_ADDRESS); - Cw1155Address = Cw1155Address_; + name = name_; + symbol = symbol_; } function supportsInterface(bytes4 interfaceId) public pure override(ERC2981, ERC1155) returns (bool) { @@ -78,6 +81,25 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { return JsonPrecompile.extractAsUint256(response, "approved") == 1; } + // ERC1155Supply + function totalSupply() public view virtual returns (uint256) { + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes("{\"num_tokens\":{}}")); + return JsonPrecompile.extractAsUint256(response, "count"); + } + + function totalSupply(uint256 id) public view virtual returns (uint256) { + string memory query = string.concat( + string.concat("{\"num_tokens\":{\"token_id\":\"", Strings.toString(id)), + "\"}}" + ); + bytes memory response = WasmdPrecompile.query(Cw1155Address, bytes(query)); + return JsonPrecompile.extractAsUint256(response, "count"); + } + + function exists(uint256 id) public view virtual returns (bool) { + return totalSupply(id) > 0; + } + // 2981 function royaltyInfo(uint256 tokenId, uint256 salePrice) public view override returns (address, uint256) { bytes memory checkRoyaltyResponse = WasmdPrecompile.query(Cw1155Address, bytes("{\"extension\":{\"msg\":{\"check_royalties\":{}}}}")); diff --git a/contracts/test/CW1155toERC1155PointerTest.t.sol b/contracts/test/CW1155ERC1155PointerTest.t.sol similarity index 99% rename from contracts/test/CW1155toERC1155PointerTest.t.sol rename to contracts/test/CW1155ERC1155PointerTest.t.sol index c62d08fee..6eb46dd18 100644 --- a/contracts/test/CW1155toERC1155PointerTest.t.sol +++ b/contracts/test/CW1155ERC1155PointerTest.t.sol @@ -90,7 +90,7 @@ contract CW1155ERC1155PointerTest is Test { MockAddr mockAddr; function setUp() public { - pointer = new CW1155ERC1155Pointer(MockCWContractAddress, "ipfs://uri.json"); + pointer = new CW1155ERC1155Pointer(MockCWContractAddress, "Test", "TEST"); mockWasmd = new MockWasmd(); mockJson = new MockJson(); mockAddr = new MockAddr(); diff --git a/example/contracts/erc1155/ERC1155Example.abi b/example/contracts/erc1155/ERC1155Example.abi new file mode 100644 index 000000000..7941ac8f6 --- /dev/null +++ b/example/contracts/erc1155/ERC1155Example.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/example/contracts/erc1155/ERC1155Example.bin b/example/contracts/erc1155/ERC1155Example.bin new file mode 100644 index 000000000..54e80cfce --- /dev/null +++ b/example/contracts/erc1155/ERC1155Example.bin @@ -0,0 +1 @@ +60806040526040518060400160405280600c81526020017f44756d6d79455243313135350000000000000000000000000000000000000000815250600790816100489190611592565b506040518060400160405280600581526020017f44554d4d590000000000000000000000000000000000000000000000000000008152506008908161008d9190611592565b506040518060400160405280601881526020017f68747470733a2f2f6578616d706c652e636f6d2f7b69647d0000000000000000815250600990816100d29190611592565b5073f39fd6e51aad88f6f4ce6ab8827279cfffb92266600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073f39fd6e51aad88f6f4ce6ab8827279cfffb92267600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550348015610186575f80fd5b5060098054610194906113bc565b80601f01602080910402602001604051908101604052809291908181526020018280546101c0906113bc565b801561020b5780601f106101e25761010080835404028352916020019161020b565b820191905f5260205f20905b8154815290600101906020018083116101ee57829003601f168201915b505050505061021f8161078860201b60201c565b50610250600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661079b60201b60201c565b5f600667ffffffffffffffff81111561026c5761026b611362565b5b60405190808252806020026020018201604052801561029a5781602001602082028036833780820191505090505b5090505f815f815181106102b1576102b0611661565b5b6020026020010181815250506001816001815181106102d3576102d2611661565b5b6020026020010181815250506002816002815181106102f5576102f4611661565b5b60200260200101818152505060038160038151811061031757610316611661565b5b60200260200101818152505060048160048151811061033957610338611661565b5b60200260200101818152505060058160058151811061035b5761035a611661565b5b6020026020010181815250505f600667ffffffffffffffff81111561038357610382611362565b5b6040519080825280602002602001820160405280156103b15781602001602082028036833780820191505090505b509050600a815f815181106103c9576103c8611661565b5b602002602001018181525050600b816001815181106103eb576103ea611661565b5b602002602001018181525050600c8160028151811061040d5761040c611661565b5b602002602001018181525050600d8160038151811061042f5761042e611661565b5b602002602001018181525050600e8160048151811061045157610450611661565b5b602002602001018181525050600f8160058151811061047357610472611661565b5b6020026020010181815250506104e7600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683836040518060400160405280600381526020017f30783000000000000000000000000000000000000000000000000000000000008152506107b060201b60201c565b5f600667ffffffffffffffff81111561050357610502611362565b5b6040519080825280602002602001820160405280156105315781602001602082028036833780820191505090505b5090506004815f8151811061054957610548611661565b5b60200260200101818152505060058160018151811061056b5761056a611661565b5b60200260200101818152505060068160028151811061058d5761058c611661565b5b6020026020010181815250506007816003815181106105af576105ae611661565b5b6020026020010181815250506008816004815181106105d1576105d0611661565b5b6020026020010181815250506009816005815181106105f3576105f2611661565b5b6020026020010181815250505f600667ffffffffffffffff81111561061b5761061a611362565b5b6040519080825280602002602001820160405280156106495781602001602082028036833780820191505090505b509050600a815f8151811061066157610660611661565b5b602002602001018181525050600b8160018151811061068357610682611661565b5b602002602001018181525050600c816002815181106106a5576106a4611661565b5b602002602001018181525050600d816003815181106106c7576106c6611661565b5b602002602001018181525050600e816004815181106106e9576106e8611661565b5b602002602001018181525050600f8160058151811061070b5761070a611661565b5b60200260200101818152505061077f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683836040518060400160405280600381526020017f30783000000000000000000000000000000000000000000000000000000000008152506107b060201b60201c565b50505050611acb565b80600290816107979190611592565b5050565b6107ad816101f461083960201b60201c565b50565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610820575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161081791906116cd565b60405180910390fd5b6108335f858585856109da60201b60201c565b50505050565b5f610848610a9e60201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156108ad5781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016108a492919061173c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361091d575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161091491906116cd565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060055f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b6109ec85858585610aa760201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610a97575f610a2e610c4a60201b60201c565b90506001845103610a80575f610a4d5f86610c5160201b90919060201c565b90505f610a635f86610c5160201b90919060201c565b9050610a79838989858589610c6460201b60201c565b5050610a95565b610a94818787878787610e1360201b60201c565b5b505b5050505050565b5f612710905090565b610ab984848484610fc260201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610b8c575f805b8351811015610b71575f838281518110610b0c57610b0b611661565b5b602002602001015190508060035f878581518110610b2d57610b2c611661565b5b602002602001015181526020019081526020015f205f828254610b509190611790565b925050819055508083610b639190611790565b925050806001019050610aef565b508060045f828254610b839190611790565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610c44575f805b8351811015610c32575f838281518110610bdf57610bde611661565b5b602002602001015190508060035f878581518110610c0057610bff611661565b5b602002602001015181526020019081526020015f205f8282540392505081905550808301925050806001019050610bc2565b508060045f8282540392505081905550505b50505050565b5f33905090565b5f60208202602084010151905092915050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115610e0b578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401610cc4959493929190611833565b6020604051808303815f875af1925050508015610cff57506040513d601f19601f82011682018060405250810190610cfc91906118e4565b60015b610d80573d805f8114610d2d576040519150601f19603f3d011682016040523d82523d5f602084013e610d32565b606091505b505f815103610d7857846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610d6f91906116cd565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610e0957846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610e0091906116cd565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115610fba578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401610e739594939291906119c6565b6020604051808303815f875af1925050508015610eae57506040513d601f19601f82011682018060405250810190610eab91906118e4565b60015b610f2f573d805f8114610edc576040519150601f19603f3d011682016040523d82523d5f602084013e610ee1565b606091505b505f815103610f2757846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610f1e91906116cd565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610fb857846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610faf91906116cd565b60405180910390fd5b505b505050505050565b805182511461100c57815181516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611003929190611a2c565b60405180910390fd5b5f61101b610c4a60201b60201c565b90505f5b8351811015611217575f61103c8286610c5160201b90919060201c565b90505f6110528386610c5160201b90919060201c565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614611175575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561112157888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016111189493929190611a53565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461120a57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546112029190611790565b925050819055505b505080600101905061101f565b5060018351036112d2575f6112355f85610c5160201b90919060201c565b90505f61124b5f85610c5160201b90919060201c565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516112c3929190611a2c565b60405180910390a45050611351565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611348929190611a96565b60405180910390a45b5050505050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806113d357607f821691505b6020821081036113e6576113e561138f565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026114487fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261140d565b611452868361140d565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61149661149161148c8461146a565b611473565b61146a565b9050919050565b5f819050919050565b6114af8361147c565b6114c36114bb8261149d565b848454611419565b825550505050565b5f90565b6114d76114cb565b6114e28184846114a6565b505050565b5b81811015611505576114fa5f826114cf565b6001810190506114e8565b5050565b601f82111561154a5761151b816113ec565b611524846113fe565b81016020851015611533578190505b61154761153f856113fe565b8301826114e7565b50505b505050565b5f82821c905092915050565b5f61156a5f198460080261154f565b1980831691505092915050565b5f611582838361155b565b9150826002028217905092915050565b61159b82611358565b67ffffffffffffffff8111156115b4576115b3611362565b5b6115be82546113bc565b6115c9828285611509565b5f60209050601f8311600181146115fa575f84156115e8578287015190505b6115f28582611577565b865550611659565b601f198416611608866113ec565b5f5b8281101561162f5784890151825560018201915060208501945060208101905061160a565b8683101561164c5784890151611648601f89168261155b565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6116b78261168e565b9050919050565b6116c7816116ad565b82525050565b5f6020820190506116e05f8301846116be565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b5f61171761171261170d846116e6565b611473565b61146a565b9050919050565b611727816116fd565b82525050565b6117368161146a565b82525050565b5f60408201905061174f5f83018561171e565b61175c602083018461172d565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61179a8261146a565b91506117a58361146a565b92508282019050808211156117bd576117bc611763565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f611805826117c3565b61180f81856117cd565b935061181f8185602086016117dd565b611828816117eb565b840191505092915050565b5f60a0820190506118465f8301886116be565b61185360208301876116be565b611860604083018661172d565b61186d606083018561172d565b818103608083015261187f81846117fb565b90509695505050505050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6118c38161188f565b81146118cd575f80fd5b50565b5f815190506118de816118ba565b92915050565b5f602082840312156118f9576118f861188b565b5b5f611906848285016118d0565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6119418161146a565b82525050565b5f6119528383611938565b60208301905092915050565b5f602082019050919050565b5f6119748261190f565b61197e8185611919565b935061198983611929565b805f5b838110156119b95781516119a08882611947565b97506119ab8361195e565b92505060018101905061198c565b5085935050505092915050565b5f60a0820190506119d95f8301886116be565b6119e660208301876116be565b81810360408301526119f8818661196a565b90508181036060830152611a0c818561196a565b90508181036080830152611a2081846117fb565b90509695505050505050565b5f604082019050611a3f5f83018561172d565b611a4c602083018461172d565b9392505050565b5f608082019050611a665f8301876116be565b611a73602083018661172d565b611a80604083018561172d565b611a8d606083018461172d565b95945050505050565b5f6040820190508181035f830152611aae818561196a565b90508181036020830152611ac2818461196a565b90509392505050565b61283e80611ad85f395ff3fe608060405234801561000f575f80fd5b50600436106100f2575f3560e01c80634e1273f411610095578063b03b74aa11610064578063b03b74aa146102a9578063bd85b039146102c5578063e985e9c5146102f5578063f242432a14610325576100f2565b80634e1273f41461020f5780634f558e791461023f57806395d89b411461026f578063a22cb4651461028d576100f2565b80630e89341c116100d15780630e89341c1461017457806318160ddd146101a45780632a55205a146101c25780632eb2c2d6146101f3576100f2565b8062fdd58e146100f657806301ffc9a71461012657806306fdde0314610156575b5f80fd5b610110600480360381019061010b9190611b67565b610341565b60405161011d9190611bb4565b60405180910390f35b610140600480360381019061013b9190611c22565b610396565b60405161014d9190611c67565b60405180910390f35b61015e6103a7565b60405161016b9190611cf0565b60405180910390f35b61018e60048036038101906101899190611d10565b610433565b60405161019b9190611cf0565b60405180910390f35b6101ac6104c5565b6040516101b99190611bb4565b60405180910390f35b6101dc60048036038101906101d79190611d3b565b6104ce565b6040516101ea929190611d88565b60405180910390f35b61020d60048036038101906102089190611f9f565b6106aa565b005b6102296004803603810190610224919061212a565b610751565b6040516102369190612257565b60405180910390f35b61025960048036038101906102549190611d10565b610858565b6040516102669190611c67565b60405180910390f35b61027761086b565b6040516102849190611cf0565b60405180910390f35b6102a760048036038101906102a291906122a1565b6108f7565b005b6102c360048036038101906102be91906122df565b61090d565b005b6102df60048036038101906102da9190611d10565b61091c565b6040516102ec9190611bb4565b60405180910390f35b61030f600480360381019061030a919061230a565b610936565b60405161031c9190611c67565b60405180910390f35b61033f600480360381019061033a9190612348565b6109c4565b005b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f6103a082610a6b565b9050919050565b600780546103b490612408565b80601f01602080910402602001604051908101604052809291908181526020018280546103e090612408565b801561042b5780601f106104025761010080835404028352916020019161042b565b820191905f5260205f20905b81548152906001019060200180831161040e57829003601f168201915b505050505081565b60606002805461044290612408565b80601f016020809104026020016040519081016040528092919081815260200182805461046e90612408565b80156104b95780601f10610490576101008083540402835291602001916104b9565b820191905f5260205f20905b81548152906001019060200180831161049c57829003601f168201915b50505050509050919050565b5f600454905090565b5f805f60065f8681526020019081526020015f206040518060400160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505090505f73ffffffffffffffffffffffffffffffffffffffff16815f015173ffffffffffffffffffffffffffffffffffffffff16036106575760056040518060400160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505090505b5f610660610ae4565b6bffffffffffffffffffffffff1682602001516bffffffffffffffffffffffff168661068c9190612465565b61069691906124d3565b9050815f0151819350935050509250929050565b5f6106b3610aed565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141580156106f857506106f68682610936565b155b1561073c5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610733929190612503565b60405180910390fd5b6107498686868686610af4565b505050505050565b6060815183511461079d57815183516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161079492919061252a565b60405180910390fd5b5f835167ffffffffffffffff8111156107b9576107b8611db3565b5b6040519080825280602002602001820160405280156107e75781602001602082028036833780820191505090505b5090505f5b845181101561084d5761082361080b8287610be890919063ffffffff16565b61081e8387610bfb90919063ffffffff16565b610341565b82828151811061083657610835612551565b5b6020026020010181815250508060010190506107ec565b508091505092915050565b5f806108638361091c565b119050919050565b6008805461087890612408565b80601f01602080910402602001604051908101604052809291908181526020018280546108a490612408565b80156108ef5780601f106108c6576101008083540402835291602001916108ef565b820191905f5260205f20905b8154815290600101906020018083116108d257829003601f168201915b505050505081565b610909610902610aed565b8383610c0e565b5050565b610919816101f4610d77565b50565b5f60035f8381526020019081526020015f20549050919050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f6109cd610aed565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610a125750610a108682610936565b155b15610a565780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610a4d929190612503565b60405180910390fd5b610a638686868686610f12565b505050505050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610add5750610adc82611018565b5b9050919050565b5f612710905090565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610b64575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610b5b919061257e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610bd4575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401610bcb919061257e565b60405180910390fd5b610be185858585856110f9565b5050505050565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610c7e575f6040517fced3e100000000000000000000000000000000000000000000000000000000008152600401610c75919061257e565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610d6a9190611c67565b60405180910390a3505050565b5f610d80610ae4565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115610de55781816040517f6f483d09000000000000000000000000000000000000000000000000000000008152600401610ddc9291906125e7565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e55575f6040517fb6d9900a000000000000000000000000000000000000000000000000000000008152600401610e4c919061257e565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060055f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f82575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401610f79919061257e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610ff2575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401610fe9919061257e565b60405180910390fd5b5f80610ffe85856111a5565b9150915061100f87878484876110f9565b50505050505050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110e257507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806110f257506110f1826111d5565b5b9050919050565b6111058585858561123e565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461119e575f611141610aed565b9050600184510361118d575f6111605f86610bfb90919063ffffffff16565b90505f6111765f86610bfb90919063ffffffff16565b90506111868389898585896113db565b505061119c565b61119b81878787878761158a565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b61124a84848484611739565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361131d575f805b8351811015611302575f83828151811061129d5761129c612551565b5b602002602001015190508060035f8785815181106112be576112bd612551565b5b602002602001015181526020019081526020015f205f8282546112e1919061260e565b9250508190555080836112f4919061260e565b925050806001019050611280565b508060045f828254611314919061260e565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036113d5575f805b83518110156113c3575f8382815181106113705761136f612551565b5b602002602001015190508060035f87858151811061139157611390612551565b5b602002602001015181526020019081526020015f205f8282540392505081905550808301925050806001019050611353565b508060045f8282540392505081905550505b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611582578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b815260040161143b959493929190612693565b6020604051808303815f875af192505050801561147657506040513d601f19601f8201168201806040525081019061147391906126ff565b60015b6114f7573d805f81146114a4576040519150601f19603f3d011682016040523d82523d5f602084013e6114a9565b606091505b505f8151036114ef57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016114e6919061257e565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461158057846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611577919061257e565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611731578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016115ea95949392919061272a565b6020604051808303815f875af192505050801561162557506040513d601f19601f8201168201806040525081019061162291906126ff565b60015b6116a6573d805f8114611653576040519150601f19603f3d011682016040523d82523d5f602084013e611658565b606091505b505f81510361169e57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611695919061257e565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461172f57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611726919061257e565b60405180910390fd5b505b505050505050565b805182511461178357815181516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161177a92919061252a565b60405180910390fd5b5f61178c610aed565b90505f5b8351811015611988575f6117ad8286610bfb90919063ffffffff16565b90505f6117c38386610bfb90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146118e6575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561189257888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016118899493929190612790565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461197b57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611973919061260e565b925050819055505b5050806001019050611790565b506001835103611a43575f6119a65f85610bfb90919063ffffffff16565b90505f6119bc5f85610bfb90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051611a3492919061252a565b60405180910390a45050611ac2565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611ab99291906127d3565b60405180910390a45b5050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611b0382611ada565b9050919050565b611b1381611af9565b8114611b1d575f80fd5b50565b5f81359050611b2e81611b0a565b92915050565b5f819050919050565b611b4681611b34565b8114611b50575f80fd5b50565b5f81359050611b6181611b3d565b92915050565b5f8060408385031215611b7d57611b7c611ad2565b5b5f611b8a85828601611b20565b9250506020611b9b85828601611b53565b9150509250929050565b611bae81611b34565b82525050565b5f602082019050611bc75f830184611ba5565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611c0181611bcd565b8114611c0b575f80fd5b50565b5f81359050611c1c81611bf8565b92915050565b5f60208284031215611c3757611c36611ad2565b5b5f611c4484828501611c0e565b91505092915050565b5f8115159050919050565b611c6181611c4d565b82525050565b5f602082019050611c7a5f830184611c58565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f611cc282611c80565b611ccc8185611c8a565b9350611cdc818560208601611c9a565b611ce581611ca8565b840191505092915050565b5f6020820190508181035f830152611d088184611cb8565b905092915050565b5f60208284031215611d2557611d24611ad2565b5b5f611d3284828501611b53565b91505092915050565b5f8060408385031215611d5157611d50611ad2565b5b5f611d5e85828601611b53565b9250506020611d6f85828601611b53565b9150509250929050565b611d8281611af9565b82525050565b5f604082019050611d9b5f830185611d79565b611da86020830184611ba5565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611de982611ca8565b810181811067ffffffffffffffff82111715611e0857611e07611db3565b5b80604052505050565b5f611e1a611ac9565b9050611e268282611de0565b919050565b5f67ffffffffffffffff821115611e4557611e44611db3565b5b602082029050602081019050919050565b5f80fd5b5f611e6c611e6784611e2b565b611e11565b90508083825260208201905060208402830185811115611e8f57611e8e611e56565b5b835b81811015611eb85780611ea48882611b53565b845260208401935050602081019050611e91565b5050509392505050565b5f82601f830112611ed657611ed5611daf565b5b8135611ee6848260208601611e5a565b91505092915050565b5f80fd5b5f67ffffffffffffffff821115611f0d57611f0c611db3565b5b611f1682611ca8565b9050602081019050919050565b828183375f83830152505050565b5f611f43611f3e84611ef3565b611e11565b905082815260208101848484011115611f5f57611f5e611eef565b5b611f6a848285611f23565b509392505050565b5f82601f830112611f8657611f85611daf565b5b8135611f96848260208601611f31565b91505092915050565b5f805f805f60a08688031215611fb857611fb7611ad2565b5b5f611fc588828901611b20565b9550506020611fd688828901611b20565b945050604086013567ffffffffffffffff811115611ff757611ff6611ad6565b5b61200388828901611ec2565b935050606086013567ffffffffffffffff81111561202457612023611ad6565b5b61203088828901611ec2565b925050608086013567ffffffffffffffff81111561205157612050611ad6565b5b61205d88828901611f72565b9150509295509295909350565b5f67ffffffffffffffff82111561208457612083611db3565b5b602082029050602081019050919050565b5f6120a76120a28461206a565b611e11565b905080838252602082019050602084028301858111156120ca576120c9611e56565b5b835b818110156120f357806120df8882611b20565b8452602084019350506020810190506120cc565b5050509392505050565b5f82601f83011261211157612110611daf565b5b8135612121848260208601612095565b91505092915050565b5f80604083850312156121405761213f611ad2565b5b5f83013567ffffffffffffffff81111561215d5761215c611ad6565b5b612169858286016120fd565b925050602083013567ffffffffffffffff81111561218a57612189611ad6565b5b61219685828601611ec2565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6121d281611b34565b82525050565b5f6121e383836121c9565b60208301905092915050565b5f602082019050919050565b5f612205826121a0565b61220f81856121aa565b935061221a836121ba565b805f5b8381101561224a57815161223188826121d8565b975061223c836121ef565b92505060018101905061221d565b5085935050505092915050565b5f6020820190508181035f83015261226f81846121fb565b905092915050565b61228081611c4d565b811461228a575f80fd5b50565b5f8135905061229b81612277565b92915050565b5f80604083850312156122b7576122b6611ad2565b5b5f6122c485828601611b20565b92505060206122d58582860161228d565b9150509250929050565b5f602082840312156122f4576122f3611ad2565b5b5f61230184828501611b20565b91505092915050565b5f80604083850312156123205761231f611ad2565b5b5f61232d85828601611b20565b925050602061233e85828601611b20565b9150509250929050565b5f805f805f60a0868803121561236157612360611ad2565b5b5f61236e88828901611b20565b955050602061237f88828901611b20565b945050604061239088828901611b53565b93505060606123a188828901611b53565b925050608086013567ffffffffffffffff8111156123c2576123c1611ad6565b5b6123ce88828901611f72565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061241f57607f821691505b602082108103612432576124316123db565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61246f82611b34565b915061247a83611b34565b925082820261248881611b34565b9150828204841483151761249f5761249e612438565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6124dd82611b34565b91506124e883611b34565b9250826124f8576124f76124a6565b5b828204905092915050565b5f6040820190506125165f830185611d79565b6125236020830184611d79565b9392505050565b5f60408201905061253d5f830185611ba5565b61254a6020830184611ba5565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6020820190506125915f830184611d79565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b5f819050919050565b5f6125d16125cc6125c784612597565b6125ae565b611b34565b9050919050565b6125e1816125b7565b82525050565b5f6040820190506125fa5f8301856125d8565b6126076020830184611ba5565b9392505050565b5f61261882611b34565b915061262383611b34565b925082820190508082111561263b5761263a612438565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f61266582612641565b61266f818561264b565b935061267f818560208601611c9a565b61268881611ca8565b840191505092915050565b5f60a0820190506126a65f830188611d79565b6126b36020830187611d79565b6126c06040830186611ba5565b6126cd6060830185611ba5565b81810360808301526126df818461265b565b90509695505050505050565b5f815190506126f981611bf8565b92915050565b5f6020828403121561271457612713611ad2565b5b5f612721848285016126eb565b91505092915050565b5f60a08201905061273d5f830188611d79565b61274a6020830187611d79565b818103604083015261275c81866121fb565b9050818103606083015261277081856121fb565b90508181036080830152612784818461265b565b90509695505050505050565b5f6080820190506127a35f830187611d79565b6127b06020830186611ba5565b6127bd6040830185611ba5565b6127ca6060830184611ba5565b95945050505050565b5f6040820190508181035f8301526127eb81856121fb565b905081810360208301526127ff81846121fb565b9050939250505056fea2646970667358221220d9517782577e383c23f0dae2951795065070c4131e635975dfb8979986ef9a6564736f6c63430008190033 \ No newline at end of file diff --git a/example/contracts/erc1155/ERC1155Example.sol b/example/contracts/erc1155/ERC1155Example.sol new file mode 100644 index 000000000..407793362 --- /dev/null +++ b/example/contracts/erc1155/ERC1155Example.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/common/ERC2981.sol"; +import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; + +contract ERC1155Example is ERC1155Supply,ERC2981 { + string public name = "DummyERC1155"; + + string public symbol = "DUMMY"; + + string private _uri = "https://example.com/{id}"; + + address private _randomAddress1 = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; + address private _randomAddress2 = 0xF39fD6e51Aad88F6f4CE6AB8827279CFffb92267; + + constructor() ERC1155(_uri) { + setDefaultRoyalty(_randomAddress1); + + uint256[] memory tids1 = new uint256[](6); + tids1[0] = 0; + tids1[1] = 1; + tids1[2] = 2; + tids1[3] = 3; + tids1[4] = 4; + tids1[5] = 5; + uint256[] memory values1 = new uint256[](6); + values1[0] = 10; + values1[1] = 11; + values1[2] = 12; + values1[3] = 13; + values1[4] = 14; + values1[5] = 15; + _mintBatch(_randomAddress1, tids1, values1, '0x0'); + + uint256[] memory tids2 = new uint256[](6); + tids2[0] = 4; + tids2[1] = 5; + tids2[2] = 6; + tids2[3] = 7; + tids2[4] = 8; + tids2[5] = 9; + uint256[] memory values2 = new uint256[](6); + values2[0] = 10; + values2[1] = 11; + values2[2] = 12; + values2[3] = 13; + values2[4] = 14; + values2[5] = 15; + _mintBatch(_randomAddress2, tids2, values2, '0x0'); + } + + function supportsInterface(bytes4 interfaceId) public view override(ERC1155, ERC2981) returns (bool) { + return super.supportsInterface(interfaceId); + } + + function setDefaultRoyalty(address receiver) public { + _setDefaultRoyalty(receiver, 500); + } +} diff --git a/example/contracts/erc1155/erc1155.go b/example/contracts/erc1155/erc1155.go new file mode 100644 index 000000000..fc60f6d8b --- /dev/null +++ b/example/contracts/erc1155/erc1155.go @@ -0,0 +1,1234 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc1155 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// Erc1155MetaData contains all meta data concerning the Erc1155 contract. +var Erc1155MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"exists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"setDefaultRoyalty\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// Erc1155ABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc1155MetaData.ABI instead. +var Erc1155ABI = Erc1155MetaData.ABI + +// Erc1155 is an auto generated Go binding around an Ethereum contract. +type Erc1155 struct { + Erc1155Caller // Read-only binding to the contract + Erc1155Transactor // Write-only binding to the contract + Erc1155Filterer // Log filterer for contract events +} + +// Erc1155Caller is an auto generated read-only Go binding around an Ethereum contract. +type Erc1155Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc1155Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc1155Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc1155Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc1155Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc1155Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc1155Session struct { + Contract *Erc1155 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc1155CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc1155CallerSession struct { + Contract *Erc1155Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc1155TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc1155TransactorSession struct { + Contract *Erc1155Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc1155Raw is an auto generated low-level Go binding around an Ethereum contract. +type Erc1155Raw struct { + Contract *Erc1155 // Generic contract binding to access the raw methods on +} + +// Erc1155CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc1155CallerRaw struct { + Contract *Erc1155Caller // Generic read-only contract binding to access the raw methods on +} + +// Erc1155TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc1155TransactorRaw struct { + Contract *Erc1155Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc1155 creates a new instance of Erc1155, bound to a specific deployed contract. +func NewErc1155(address common.Address, backend bind.ContractBackend) (*Erc1155, error) { + contract, err := bindErc1155(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc1155{Erc1155Caller: Erc1155Caller{contract: contract}, Erc1155Transactor: Erc1155Transactor{contract: contract}, Erc1155Filterer: Erc1155Filterer{contract: contract}}, nil +} + +// NewErc1155Caller creates a new read-only instance of Erc1155, bound to a specific deployed contract. +func NewErc1155Caller(address common.Address, caller bind.ContractCaller) (*Erc1155Caller, error) { + contract, err := bindErc1155(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc1155Caller{contract: contract}, nil +} + +// NewErc1155Transactor creates a new write-only instance of Erc1155, bound to a specific deployed contract. +func NewErc1155Transactor(address common.Address, transactor bind.ContractTransactor) (*Erc1155Transactor, error) { + contract, err := bindErc1155(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc1155Transactor{contract: contract}, nil +} + +// NewErc1155Filterer creates a new log filterer instance of Erc1155, bound to a specific deployed contract. +func NewErc1155Filterer(address common.Address, filterer bind.ContractFilterer) (*Erc1155Filterer, error) { + contract, err := bindErc1155(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc1155Filterer{contract: contract}, nil +} + +// bindErc1155 binds a generic wrapper to an already deployed contract. +func bindErc1155(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Erc1155MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc1155 *Erc1155Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc1155.Contract.Erc1155Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc1155 *Erc1155Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc1155.Contract.Erc1155Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc1155 *Erc1155Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc1155.Contract.Erc1155Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc1155 *Erc1155CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc1155.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc1155 *Erc1155TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc1155.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc1155 *Erc1155TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc1155.Contract.contract.Transact(opts, method, params...) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155Caller) BalanceOf(opts *bind.CallOpts, account common.Address, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "balanceOf", account, id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155Session) BalanceOf(account common.Address, id *big.Int) (*big.Int, error) { + return _Erc1155.Contract.BalanceOf(&_Erc1155.CallOpts, account, id) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x00fdd58e. +// +// Solidity: function balanceOf(address account, uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155CallerSession) BalanceOf(account common.Address, id *big.Int) (*big.Int, error) { + return _Erc1155.Contract.BalanceOf(&_Erc1155.CallOpts, account, id) +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[]) +func (_Erc1155 *Erc1155Caller) BalanceOfBatch(opts *bind.CallOpts, accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "balanceOfBatch", accounts, ids) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[]) +func (_Erc1155 *Erc1155Session) BalanceOfBatch(accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + return _Erc1155.Contract.BalanceOfBatch(&_Erc1155.CallOpts, accounts, ids) +} + +// BalanceOfBatch is a free data retrieval call binding the contract method 0x4e1273f4. +// +// Solidity: function balanceOfBatch(address[] accounts, uint256[] ids) view returns(uint256[]) +func (_Erc1155 *Erc1155CallerSession) BalanceOfBatch(accounts []common.Address, ids []*big.Int) ([]*big.Int, error) { + return _Erc1155.Contract.BalanceOfBatch(&_Erc1155.CallOpts, accounts, ids) +} + +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Erc1155 *Erc1155Caller) Exists(opts *bind.CallOpts, id *big.Int) (bool, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "exists", id) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Erc1155 *Erc1155Session) Exists(id *big.Int) (bool, error) { + return _Erc1155.Contract.Exists(&_Erc1155.CallOpts, id) +} + +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Erc1155 *Erc1155CallerSession) Exists(id *big.Int) (bool, error) { + return _Erc1155.Contract.Exists(&_Erc1155.CallOpts, id) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address account, address operator) view returns(bool) +func (_Erc1155 *Erc1155Caller) IsApprovedForAll(opts *bind.CallOpts, account common.Address, operator common.Address) (bool, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "isApprovedForAll", account, operator) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address account, address operator) view returns(bool) +func (_Erc1155 *Erc1155Session) IsApprovedForAll(account common.Address, operator common.Address) (bool, error) { + return _Erc1155.Contract.IsApprovedForAll(&_Erc1155.CallOpts, account, operator) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address account, address operator) view returns(bool) +func (_Erc1155 *Erc1155CallerSession) IsApprovedForAll(account common.Address, operator common.Address) (bool, error) { + return _Erc1155.Contract.IsApprovedForAll(&_Erc1155.CallOpts, account, operator) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc1155 *Erc1155Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc1155 *Erc1155Session) Name() (string, error) { + return _Erc1155.Contract.Name(&_Erc1155.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc1155 *Erc1155CallerSession) Name() (string, error) { + return _Erc1155.Contract.Name(&_Erc1155.CallOpts) +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Erc1155 *Erc1155Caller) RoyaltyInfo(opts *bind.CallOpts, tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "royaltyInfo", tokenId, salePrice) + + if err != nil { + return *new(common.Address), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return out0, out1, err + +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Erc1155 *Erc1155Session) RoyaltyInfo(tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + return _Erc1155.Contract.RoyaltyInfo(&_Erc1155.CallOpts, tokenId, salePrice) +} + +// RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. +// +// Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) +func (_Erc1155 *Erc1155CallerSession) RoyaltyInfo(tokenId *big.Int, salePrice *big.Int) (common.Address, *big.Int, error) { + return _Erc1155.Contract.RoyaltyInfo(&_Erc1155.CallOpts, tokenId, salePrice) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc1155 *Erc1155Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc1155 *Erc1155Session) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Erc1155.Contract.SupportsInterface(&_Erc1155.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc1155 *Erc1155CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Erc1155.Contract.SupportsInterface(&_Erc1155.CallOpts, interfaceId) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc1155 *Erc1155Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc1155 *Erc1155Session) Symbol() (string, error) { + return _Erc1155.Contract.Symbol(&_Erc1155.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc1155 *Erc1155CallerSession) Symbol() (string, error) { + return _Erc1155.Contract.Symbol(&_Erc1155.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc1155 *Erc1155Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc1155 *Erc1155Session) TotalSupply() (*big.Int, error) { + return _Erc1155.Contract.TotalSupply(&_Erc1155.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc1155 *Erc1155CallerSession) TotalSupply() (*big.Int, error) { + return _Erc1155.Contract.TotalSupply(&_Erc1155.CallOpts) +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155Caller) TotalSupply0(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "totalSupply0", id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155Session) TotalSupply0(id *big.Int) (*big.Int, error) { + return _Erc1155.Contract.TotalSupply0(&_Erc1155.CallOpts, id) +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Erc1155 *Erc1155CallerSession) TotalSupply0(id *big.Int) (*big.Int, error) { + return _Erc1155.Contract.TotalSupply0(&_Erc1155.CallOpts, id) +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 ) view returns(string) +func (_Erc1155 *Erc1155Caller) Uri(opts *bind.CallOpts, arg0 *big.Int) (string, error) { + var out []interface{} + err := _Erc1155.contract.Call(opts, &out, "uri", arg0) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 ) view returns(string) +func (_Erc1155 *Erc1155Session) Uri(arg0 *big.Int) (string, error) { + return _Erc1155.Contract.Uri(&_Erc1155.CallOpts, arg0) +} + +// Uri is a free data retrieval call binding the contract method 0x0e89341c. +// +// Solidity: function uri(uint256 ) view returns(string) +func (_Erc1155 *Erc1155CallerSession) Uri(arg0 *big.Int) (string, error) { + return _Erc1155.Contract.Uri(&_Erc1155.CallOpts, arg0) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] values, bytes data) returns() +func (_Erc1155 *Erc1155Transactor) SafeBatchTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, ids []*big.Int, values []*big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.contract.Transact(opts, "safeBatchTransferFrom", from, to, ids, values, data) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] values, bytes data) returns() +func (_Erc1155 *Erc1155Session) SafeBatchTransferFrom(from common.Address, to common.Address, ids []*big.Int, values []*big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.Contract.SafeBatchTransferFrom(&_Erc1155.TransactOpts, from, to, ids, values, data) +} + +// SafeBatchTransferFrom is a paid mutator transaction binding the contract method 0x2eb2c2d6. +// +// Solidity: function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] values, bytes data) returns() +func (_Erc1155 *Erc1155TransactorSession) SafeBatchTransferFrom(from common.Address, to common.Address, ids []*big.Int, values []*big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.Contract.SafeBatchTransferFrom(&_Erc1155.TransactOpts, from, to, ids, values, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes data) returns() +func (_Erc1155 *Erc1155Transactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, id *big.Int, value *big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.contract.Transact(opts, "safeTransferFrom", from, to, id, value, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes data) returns() +func (_Erc1155 *Erc1155Session) SafeTransferFrom(from common.Address, to common.Address, id *big.Int, value *big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.Contract.SafeTransferFrom(&_Erc1155.TransactOpts, from, to, id, value, data) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0xf242432a. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes data) returns() +func (_Erc1155 *Erc1155TransactorSession) SafeTransferFrom(from common.Address, to common.Address, id *big.Int, value *big.Int, data []byte) (*types.Transaction, error) { + return _Erc1155.Contract.SafeTransferFrom(&_Erc1155.TransactOpts, from, to, id, value, data) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Erc1155 *Erc1155Transactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, approved bool) (*types.Transaction, error) { + return _Erc1155.contract.Transact(opts, "setApprovalForAll", operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Erc1155 *Erc1155Session) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _Erc1155.Contract.SetApprovalForAll(&_Erc1155.TransactOpts, operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_Erc1155 *Erc1155TransactorSession) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _Erc1155.Contract.SetApprovalForAll(&_Erc1155.TransactOpts, operator, approved) +} + +// SetDefaultRoyalty is a paid mutator transaction binding the contract method 0xb03b74aa. +// +// Solidity: function setDefaultRoyalty(address receiver) returns() +func (_Erc1155 *Erc1155Transactor) SetDefaultRoyalty(opts *bind.TransactOpts, receiver common.Address) (*types.Transaction, error) { + return _Erc1155.contract.Transact(opts, "setDefaultRoyalty", receiver) +} + +// SetDefaultRoyalty is a paid mutator transaction binding the contract method 0xb03b74aa. +// +// Solidity: function setDefaultRoyalty(address receiver) returns() +func (_Erc1155 *Erc1155Session) SetDefaultRoyalty(receiver common.Address) (*types.Transaction, error) { + return _Erc1155.Contract.SetDefaultRoyalty(&_Erc1155.TransactOpts, receiver) +} + +// SetDefaultRoyalty is a paid mutator transaction binding the contract method 0xb03b74aa. +// +// Solidity: function setDefaultRoyalty(address receiver) returns() +func (_Erc1155 *Erc1155TransactorSession) SetDefaultRoyalty(receiver common.Address) (*types.Transaction, error) { + return _Erc1155.Contract.SetDefaultRoyalty(&_Erc1155.TransactOpts, receiver) +} + +// Erc1155ApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the Erc1155 contract. +type Erc1155ApprovalForAllIterator struct { + Event *Erc1155ApprovalForAll // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc1155ApprovalForAllIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc1155ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc1155ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc1155ApprovalForAllIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc1155ApprovalForAllIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc1155ApprovalForAll represents a ApprovalForAll event raised by the Erc1155 contract. +type Erc1155ApprovalForAll struct { + Account common.Address + Operator common.Address + Approved bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Erc1155 *Erc1155Filterer) FilterApprovalForAll(opts *bind.FilterOpts, account []common.Address, operator []common.Address) (*Erc1155ApprovalForAllIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _Erc1155.contract.FilterLogs(opts, "ApprovalForAll", accountRule, operatorRule) + if err != nil { + return nil, err + } + return &Erc1155ApprovalForAllIterator{contract: _Erc1155.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil +} + +// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Erc1155 *Erc1155Filterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *Erc1155ApprovalForAll, account []common.Address, operator []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _Erc1155.contract.WatchLogs(opts, "ApprovalForAll", accountRule, operatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc1155ApprovalForAll) + if err := _Erc1155.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed account, address indexed operator, bool approved) +func (_Erc1155 *Erc1155Filterer) ParseApprovalForAll(log types.Log) (*Erc1155ApprovalForAll, error) { + event := new(Erc1155ApprovalForAll) + if err := _Erc1155.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc1155TransferBatchIterator is returned from FilterTransferBatch and is used to iterate over the raw logs and unpacked data for TransferBatch events raised by the Erc1155 contract. +type Erc1155TransferBatchIterator struct { + Event *Erc1155TransferBatch // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc1155TransferBatchIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc1155TransferBatch) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc1155TransferBatch) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc1155TransferBatchIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc1155TransferBatchIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc1155TransferBatch represents a TransferBatch event raised by the Erc1155 contract. +type Erc1155TransferBatch struct { + Operator common.Address + From common.Address + To common.Address + Ids []*big.Int + Values []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransferBatch is a free log retrieval operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Erc1155 *Erc1155Filterer) FilterTransferBatch(opts *bind.FilterOpts, operator []common.Address, from []common.Address, to []common.Address) (*Erc1155TransferBatchIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc1155.contract.FilterLogs(opts, "TransferBatch", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &Erc1155TransferBatchIterator{contract: _Erc1155.contract, event: "TransferBatch", logs: logs, sub: sub}, nil +} + +// WatchTransferBatch is a free log subscription operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Erc1155 *Erc1155Filterer) WatchTransferBatch(opts *bind.WatchOpts, sink chan<- *Erc1155TransferBatch, operator []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc1155.contract.WatchLogs(opts, "TransferBatch", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc1155TransferBatch) + if err := _Erc1155.contract.UnpackLog(event, "TransferBatch", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransferBatch is a log parse operation binding the contract event 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb. +// +// Solidity: event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +func (_Erc1155 *Erc1155Filterer) ParseTransferBatch(log types.Log) (*Erc1155TransferBatch, error) { + event := new(Erc1155TransferBatch) + if err := _Erc1155.contract.UnpackLog(event, "TransferBatch", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc1155TransferSingleIterator is returned from FilterTransferSingle and is used to iterate over the raw logs and unpacked data for TransferSingle events raised by the Erc1155 contract. +type Erc1155TransferSingleIterator struct { + Event *Erc1155TransferSingle // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc1155TransferSingleIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc1155TransferSingle) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc1155TransferSingle) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc1155TransferSingleIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc1155TransferSingleIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc1155TransferSingle represents a TransferSingle event raised by the Erc1155 contract. +type Erc1155TransferSingle struct { + Operator common.Address + From common.Address + To common.Address + Id *big.Int + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransferSingle is a free log retrieval operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Erc1155 *Erc1155Filterer) FilterTransferSingle(opts *bind.FilterOpts, operator []common.Address, from []common.Address, to []common.Address) (*Erc1155TransferSingleIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc1155.contract.FilterLogs(opts, "TransferSingle", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &Erc1155TransferSingleIterator{contract: _Erc1155.contract, event: "TransferSingle", logs: logs, sub: sub}, nil +} + +// WatchTransferSingle is a free log subscription operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Erc1155 *Erc1155Filterer) WatchTransferSingle(opts *bind.WatchOpts, sink chan<- *Erc1155TransferSingle, operator []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc1155.contract.WatchLogs(opts, "TransferSingle", operatorRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc1155TransferSingle) + if err := _Erc1155.contract.UnpackLog(event, "TransferSingle", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransferSingle is a log parse operation binding the contract event 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62. +// +// Solidity: event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +func (_Erc1155 *Erc1155Filterer) ParseTransferSingle(log types.Log) (*Erc1155TransferSingle, error) { + event := new(Erc1155TransferSingle) + if err := _Erc1155.contract.UnpackLog(event, "TransferSingle", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc1155URIIterator is returned from FilterURI and is used to iterate over the raw logs and unpacked data for URI events raised by the Erc1155 contract. +type Erc1155URIIterator struct { + Event *Erc1155URI // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc1155URIIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc1155URI) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc1155URI) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc1155URIIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc1155URIIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc1155URI represents a URI event raised by the Erc1155 contract. +type Erc1155URI struct { + Value string + Id *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterURI is a free log retrieval operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Erc1155 *Erc1155Filterer) FilterURI(opts *bind.FilterOpts, id []*big.Int) (*Erc1155URIIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _Erc1155.contract.FilterLogs(opts, "URI", idRule) + if err != nil { + return nil, err + } + return &Erc1155URIIterator{contract: _Erc1155.contract, event: "URI", logs: logs, sub: sub}, nil +} + +// WatchURI is a free log subscription operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Erc1155 *Erc1155Filterer) WatchURI(opts *bind.WatchOpts, sink chan<- *Erc1155URI, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _Erc1155.contract.WatchLogs(opts, "URI", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc1155URI) + if err := _Erc1155.contract.UnpackLog(event, "URI", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseURI is a log parse operation binding the contract event 0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b. +// +// Solidity: event URI(string value, uint256 indexed id) +func (_Erc1155 *Erc1155Filterer) ParseURI(log types.Log) (*Erc1155URI, error) { + event := new(Erc1155URI) + if err := _Erc1155.contract.UnpackLog(event, "URI", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/example/contracts/erc721/README.md b/example/contracts/erc721/README.md index e8fadec53..48fcb1f90 100644 --- a/example/contracts/erc721/README.md +++ b/example/contracts/erc721/README.md @@ -2,5 +2,5 @@ To regenerate these files, run: ``` solc --bin -o example/contracts/erc721 example/contracts/erc721/ERC721.sol --overwrite solc --abi -o example/contracts/erc721 example/contracts/erc721/ERC721.sol --overwrite -abigen --abi=example/contracts/erc721/ERC721.abi --pkg=erc721 --out=example/contracts/erc721/ERC721.go +abigen --abi=example/contracts/erc721/DummyERC721.abi --pkg=erc721 --out=example/contracts/erc721/ERC721.go ``` \ No newline at end of file diff --git a/wasmbinding/queries.go b/wasmbinding/queries.go index 122bb712b..2b8f59ad9 100644 --- a/wasmbinding/queries.go +++ b/wasmbinding/queries.go @@ -260,6 +260,39 @@ func (qp QueryPlugin) HandleEVMQuery(ctx sdk.Context, queryData json.RawMessage) case evmbindings.ERC721RoyaltyInfoType: c := parsedQuery.ERC721RoyaltyInfo return qp.evmHandler.HandleERC721RoyaltyInfo(ctx, c.Caller, c.ContractAddress, c.TokenID, c.SalePrice) + case evmbindings.ERC1155BatchTransferType: + c := parsedQuery.ERC1155BatchTransferPayload + return qp.evmHandler.HandleERC1155BatchTransferPayload(ctx, c.From, c.Recipient, c.TokenIDs, c.Amounts) + case evmbindings.ERC1155SetApprovalAllType: + c := parsedQuery.ERC1155SetApprovalAllPayload + return qp.evmHandler.HandleERC1155SetApprovalAllPayload(ctx, c.To, c.Approved) + case evmbindings.ERC1155IsApprovedForAllType: + c := parsedQuery.ERC1155IsApprovedForAll + return qp.evmHandler.HandleERC1155IsApprovedForAll(ctx, c.Caller, c.ContractAddress, c.Owner, c.Operator) + case evmbindings.ERC1155BalanceOfType: + c := parsedQuery.ERC1155BalanceOf + return qp.evmHandler.HandleERC1155BalanceOf(ctx, c.Caller, c.ContractAddress, c.Account, c.TokenID) + case evmbindings.ERC1155BalanceOfBatchType: + c := parsedQuery.ERC1155BalanceOfBatch + return qp.evmHandler.HandleERC1155BalanceOfBatch(ctx, c.Caller, c.ContractAddress, c.Accounts, c.TokenIDs) + case evmbindings.ERC1155UriType: + c := parsedQuery.ERC1155Uri + return qp.evmHandler.HandleERC1155Uri(ctx, c.Caller, c.ContractAddress, c.TokenID) + case evmbindings.ERC1155TotalSupplyType: + c := parsedQuery.ERC1155TotalSupply + return qp.evmHandler.HandleERC1155TotalSupply(ctx, c.Caller, c.ContractAddress) + case evmbindings.ERC1155TotalSupplyForTokenType: + c := parsedQuery.ERC1155TotalSupplyForToken + return qp.evmHandler.HandleERC1155TotalSupplyForToken(ctx, c.Caller, c.ContractAddress, c.TokenID) + case evmbindings.ERC1155TokenExistsType: + c := parsedQuery.ERC1155TokenExists + return qp.evmHandler.HandleERC1155TokenExists(ctx, c.Caller, c.ContractAddress, c.TokenID) + case evmbindings.ERC1155NameSymbolType: + c := parsedQuery.ERC1155NameSymbol + return qp.evmHandler.HandleERC1155NameSymbol(ctx, c.Caller, c.ContractAddress) + case evmbindings.ERC1155RoyaltyInfoType: + c := parsedQuery.ERC1155RoyaltyInfo + return qp.evmHandler.HandleERC1155RoyaltyInfo(ctx, c.Caller, c.ContractAddress, c.TokenID, c.SalePrice) case evmbindings.GetEvmAddressType: c := parsedQuery.GetEvmAddress return qp.evmHandler.HandleGetEvmAddress(ctx, c.SeiAddress) diff --git a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi index b76de76e1..4496f5fcf 100644 --- a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi +++ b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.abi @@ -1 +1 @@ -[{"inputs":[{"internalType":"string","name":"Cw1155Address_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplemented","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplementedOnCosmwasmContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"AddrPrecompile","outputs":[{"internalType":"contract IAddr","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Cw1155Address","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"JsonPrecompile","outputs":[{"internalType":"contract IJson","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WasmdPrecompile","outputs":[{"internalType":"contract IWasmd","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"string","name":"Cw1155Address_","type":"string"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplemented","type":"error"},{"inputs":[{"internalType":"string","name":"method","type":"string"}],"name":"NotImplementedOnCosmwasmContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"AddrPrecompile","outputs":[{"internalType":"contract IAddr","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Cw1155Address","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"JsonPrecompile","outputs":[{"internalType":"contract IJson","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WasmdPrecompile","outputs":[{"internalType":"contract IWasmd","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin index e890a5278..69b445da9 100644 --- a/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin +++ b/x/evm/artifacts/cw1155/CW1155ERC1155Pointer.bin @@ -1 +1 @@ -608060405234801561000f575f80fd5b5060405161499c38038061499c8339818101604052810190610031919061027f565b806100418161011f60201b60201c565b5061100260065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100460085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600590816101179190610502565b5050506105d1565b806002908161012e9190610502565b5050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101918261014b565b810181811067ffffffffffffffff821117156101b0576101af61015b565b5b80604052505050565b5f6101c2610132565b90506101ce8282610188565b919050565b5f67ffffffffffffffff8211156101ed576101ec61015b565b5b6101f68261014b565b9050602081019050919050565b8281835e5f83830152505050565b5f61022361021e846101d3565b6101b9565b90508281526020810184848401111561023f5761023e610147565b5b61024a848285610203565b509392505050565b5f82601f83011261026657610265610143565b5b8151610276848260208601610211565b91505092915050565b5f80604083850312156102955761029461013b565b5b5f83015167ffffffffffffffff8111156102b2576102b161013f565b5b6102be85828601610252565b925050602083015167ffffffffffffffff8111156102df576102de61013f565b5b6102eb85828601610252565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061034357607f821691505b602082108103610356576103556102ff565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026103b87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261037d565b6103c2868361037d565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104066104016103fc846103da565b6103e3565b6103da565b9050919050565b5f819050919050565b61041f836103ec565b61043361042b8261040d565b848454610389565b825550505050565b5f90565b61044761043b565b610452818484610416565b505050565b5b818110156104755761046a5f8261043f565b600181019050610458565b5050565b601f8211156104ba5761048b8161035c565b6104948461036e565b810160208510156104a3578190505b6104b76104af8561036e565b830182610457565b50505b505050565b5f82821c905092915050565b5f6104da5f19846008026104bf565b1980831691505092915050565b5f6104f283836104cb565b9150826002028217905092915050565b61050b826102f5565b67ffffffffffffffff8111156105245761052361015b565b5b61052e825461032c565b610539828285610479565b5f60209050601f83116001811461056a575f8415610558578287015190505b61056285826104e7565b8655506105c9565b601f1984166105788661035c565b5f5b8281101561059f5784890151825560018201915060208501945060208101905061057a565b868310156105bc57848901516105b8601f8916826104cb565b8355505b6001600288020188555050505b505050505050565b6143be806105de5f395ff3fe608060405234801561000f575f80fd5b50600436106100cc575f3560e01c8063a22cb4651161008a578063de4725cc11610064578063de4725cc14610235578063e985e9c514610253578063f00b025514610283578063f242432a146102a1576100cc565b8063a22cb465146101dd578063b98933a0146101f9578063c2aed30214610217576100cc565b8062fdd58e146100d057806301ffc9a7146101005780630e89341c146101305780632a55205a146101605780632eb2c2d6146101915780634e1273f4146101ad575b5f80fd5b6100ea60048036038101906100e59190612b9e565b6102bd565b6040516100f79190612beb565b60405180910390f35b61011a60048036038101906101159190612c59565b61063b565b6040516101279190612c9e565b60405180910390f35b61014a60048036038101906101459190612cb7565b6107dc565b6040516101579190612d52565b60405180910390f35b61017a60048036038101906101759190612d72565b6109ca565b604051610188929190612dbf565b60405180910390f35b6101ab60048036038101906101a69190612fd6565b610ffb565b005b6101c760048036038101906101c29190613161565b61180e565b6040516101d4919061328e565b60405180910390f35b6101f760048036038101906101f291906132d8565b611922565b005b610201611b25565b60405161020e9190612d52565b60405180910390f35b61021f611bb1565b60405161022c9190613371565b60405180910390f35b61023d611bd6565b60405161024a91906133aa565b60405180910390f35b61026d600480360381019061026891906133c3565b611bfb565b60405161027a9190612c9e565b60405180910390f35b61028b611fa1565b6040516102989190613421565b60405180910390f35b6102bb60048036038101906102b6919061343a565b611fc6565b005b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361032c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103239061353d565b60405180910390fd5b5f61040f6040518060400160405280600581526020017f6f776e657200000000000000000000000000000000000000000000000000000081525061040a60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016103c3919061355b565b5f60405180830381865afa1580156103dd573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906104059190613612565b612637565b61267f565b90505f6104616040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061045c610457876126d1565b612637565b61267f565b90505f6104f26104ed6040518060400160405280600a81526020017f62616c616e63655f6f66000000000000000000000000000000000000000000008152506104e86104e3876040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508861279b565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b815260040161055292919061379b565b5f60405180830381865afa15801561056c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610594919061383e565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982826040518263ffffffff1660e01b81526004016105f091906138cf565b602060405180830381865afa15801561060b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062f9190613916565b94505050505092915050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061070557507fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061076d57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107d557507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60605f6108366108316040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061082c610827876126d1565b612637565b61267f565b6127e9565b90505f61088061087b6040518060400160405280600a81526020017f746f6b656e5f696e666f000000000000000000000000000000000000000000008152508461267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b81526004016108e092919061379b565b5f60405180830381865afa1580156108fa573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610922919061383e565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5826040518263ffffffff1660e01b815260040161097e919061398b565b5f60405180830381865afa158015610998573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906109c0919061383e565b9350505050919050565b5f805f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d2960056040518060600160405280602c815260200161435d602c91396040518363ffffffff1660e01b8152600401610a4292919061379b565b5f60405180830381865afa158015610a5c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610a84919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401610ae19190613a08565b5f60405180830381865afa158015610afb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610b23919061383e565b90507f6273151f959616268004b58dbb21e5c851b7b8d04498b4aabee12291d22fc034818051906020012014610b8e576040517f438c4bcb000000000000000000000000000000000000000000000000000000008152600401610b8590613a85565b60405180910390fd5b5f610bde6040518060400160405280600881526020017f746f6b656e5f6964000000000000000000000000000000000000000000000000815250610bd9610bd48a6126d1565b612637565b61267f565b90505f610c306040518060400160405280600a81526020017f73616c655f707269636500000000000000000000000000000000000000000000815250610c2b610c268a6126d1565b612637565b61267f565b90505f610cc1610cbc6040518060400160405280600c81526020017f726f79616c74795f696e666f0000000000000000000000000000000000000000815250610cb7610cb287876040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525061279b565b6127e9565b61267f565b6127e9565b90505f610d51610d4c6040518060400160405280600981526020017f657874656e73696f6e0000000000000000000000000000000000000000000000815250610d47610d426040518060400160405280600381526020017f6d736700000000000000000000000000000000000000000000000000000000008152508761267f565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401610db192919061379b565b5f60405180830381865afa158015610dcb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610df3919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401610e509190613aed565b5f60405180830381865afa158015610e6a573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610e92919061383e565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982846040518263ffffffff1660e01b8152600401610eef9190613b6a565b602060405180830381865afa158015610f0a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2e9190613916565b90505f825103610f4c575f819a509a50505050505050505050610ff4565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631778e539836040518263ffffffff1660e01b8152600401610fa69190612d52565b602060405180830381865afa158015610fc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe59190613bb1565b819a509a505050505050505050505b9250929050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090613c4c565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806110a957506110a88533611bfb565b5b6110e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110df90613cda565b60405180910390fd5b815183511461112c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112390613d68565b60405180910390fd5b5f5b83518110156111c45782818151811061114a57611149613d86565b5b60200260200101516111768786848151811061116957611168613d86565b5b60200260200101516102bd565b10156111b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ae90613e23565b60405180910390fd5b808060010191505061112e565b505f6112a86040518060400160405280600481526020017f66726f6d000000000000000000000000000000000000000000000000000000008152506112a360085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b815260040161125c919061355b565b5f60405180830381865afa158015611276573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061129e9190613612565b612637565b61267f565b90505f61138d6040518060400160405280600281526020017f746f00000000000000000000000000000000000000000000000000000000000081525061138860085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b8152600401611341919061355b565b5f60405180830381865afa15801561135b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906113839190613612565b612637565b61267f565b90505f6114046040518060400160405280600c81526020017f746f6b656e5f616d6f756e7400000000000000000000000000000000000000008152506040518060400160405280600181526020017f5b0000000000000000000000000000000000000000000000000000000000000081525061267f565b90505f5b8651811015611562575f61147b6040518060400160405280600881526020017f746f6b656e5f69640000000000000000000000000000000000000000000000008152506114766114718b868151811061146457611463613d86565b5b60200260200101516126d1565b612637565b61267f565b90505f6114e76040518060400160405280600681526020017f616d6f756e7400000000000000000000000000000000000000000000000000008152506114e26114dd8b87815181106114d0576114cf613d86565b5b60200260200101516126d1565b612637565b61267f565b90508361153261152d846040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508561279b565b6127e9565b604051602001611543929190613e7b565b6040516020818303038152906040525050508080600101915050611408565b50806040516020016115749190613ec4565b604051602081830303815290604052505f61165261164d6040518060400160405280600a81526020017f73656e645f626174636800000000000000000000000000000000000000000000815250611648611643886040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525061163e8a6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508b61279b565b61279b565b6127e9565b61267f565b6127e9565b905061165d81612831565b508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8a8a6040516116d4929190613ee9565b60405180910390a45f8873ffffffffffffffffffffffffffffffffffffffff163b11156118035763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168873ffffffffffffffffffffffffffffffffffffffff1663bc197c81338c8b8b8b6040518663ffffffff1660e01b8152600401611763959493929190613f1e565b6020604051808303815f875af115801561177f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117a39190613f98565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f99061400d565b60405180910390fd5b5b505050505050505050565b6060815183511461185a57815183516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161185192919061402b565b60405180910390fd5b825167ffffffffffffffff81111561187557611874612dea565b5b6040519080825280602002602001820160405280156118a35781602001602082028036833780820191505090505b5090505f5b835181101561191b576118ef8482815181106118c7576118c6613d86565b5b60200260200101518483815181106118e2576118e1613d86565b5b60200260200101516102bd565b82828151811061190257611901613d86565b5b60200260200101818152505080806001019150506118a8565b5092915050565b5f611a0d611a086040518060400160405280600881526020017f6f70657261746f72000000000000000000000000000000000000000000000000815250611a0360085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016119bc919061355b565b5f60405180830381865afa1580156119d6573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906119fe9190613612565b612637565b61267f565b6127e9565b90508115611a6a57611a64611a5f611a5a6040518060400160405280600b81526020017f617070726f76655f616c6c0000000000000000000000000000000000000000008152508461267f565b6127e9565b612831565b50611abb565b611ab9611ab4611aaf6040518060400160405280600a81526020017f7265766f6b655f616c6c000000000000000000000000000000000000000000008152508461267f565b6127e9565b612831565b505b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611b189190612c9e565b60405180910390a3505050565b60058054611b3290613686565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5e90613686565b8015611ba95780601f10611b8057610100808354040283529160200191611ba9565b820191905f5260205f20905b815481529060010190602001808311611b8c57829003601f168201915b505050505081565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f80611cdf6040518060400160405280600581526020017f6f776e6572000000000000000000000000000000000000000000000000000000815250611cda60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b8152600401611c93919061355b565b5f60405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611cd59190613612565b612637565b61267f565b90505f611dc46040518060400160405280600881526020017f6f70657261746f72000000000000000000000000000000000000000000000000815250611dbf60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b8152600401611d78919061355b565b5f60405180830381865afa158015611d92573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dba9190613612565b612637565b61267f565b90505f611e55611e506040518060400160405280601381526020017f69735f617070726f7665645f666f725f616c6c00000000000000000000000000815250611e4b611e46876040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508861279b565b6127e9565b61267f565b6127e9565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401611eb592919061379b565b5f60405180830381865afa158015611ecf573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ef7919061383e565b9050600160075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982836040518263ffffffff1660e01b8152600401611f55919061409c565b602060405180830381865afa158015611f70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f949190613916565b1494505050505092915050565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612034576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202b90613c4c565b60405180910390fd5b8161203f86856102bd565b1015612080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207790613e23565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120c057506120bf8533611bfb565b5b6120ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f690613cda565b60405180910390fd5b5f6121e26040518060400160405280600481526020017f66726f6d000000000000000000000000000000000000000000000000000000008152506121dd60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b8152600401612196919061355b565b5f60405180830381865afa1580156121b0573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906121d89190613612565b612637565b61267f565b90505f6122c76040518060400160405280600281526020017f746f0000000000000000000000000000000000000000000000000000000000008152506122c260085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b815260040161227b919061355b565b5f60405180830381865afa158015612295573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122bd9190613612565b612637565b61267f565b90505f6123196040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061231461230f896126d1565b612637565b61267f565b90505f61236b6040518060400160405280600681526020017f616d6f756e740000000000000000000000000000000000000000000000000000815250612366612361896126d1565b612637565b61267f565b90505f61247a6124756040518060400160405280600481526020017f73656e640000000000000000000000000000000000000000000000000000000081525061247061246b896040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506124668b6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506124618d6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508e61279b565b61279b565b61279b565b6127e9565b61267f565b6127e9565b905061248581612831565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b8b6040516124fc92919061402b565b60405180910390a45f8973ffffffffffffffffffffffffffffffffffffffff163b111561262b5763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168973ffffffffffffffffffffffffffffffffffffffff1663f23a6e61338d8c8c8c6040518663ffffffff1660e01b815260040161258b9594939291906140cf565b6020604051808303815f875af11580156125a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125cb9190613f98565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461262a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126219061400d565b60405180910390fd5b5b50505050505050505050565b60608160405160200161264a919061414d565b6040516020818303038152906040526040516020016126699190614172565b6040516020818303038152906040529050919050565b60606126c961268d84612637565b6040518060400160405280600181526020017f3a000000000000000000000000000000000000000000000000000000000000008152508461279b565b905092915050565b60605f60016126df846129af565b0190505f8167ffffffffffffffff8111156126fd576126fc612dea565b5b6040519080825280601f01601f19166020018201604052801561272f5781602001600182028036833780820191505090505b5090505f82602001820190505b600115612790578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161278557612784614197565b5b0494505f850361273c575b819350505050919050565b60608383836040516020016127b1929190613e7b565b6040516020818303038152906040526040516020016127d1929190613e7b565b60405160208183030381529060405290509392505050565b6060816040516020016127fc91906141ea565b60405160208183030381529060405260405160200161281b9190614235565b6040516020818303038152906040529050919050565b60605f8061100273ffffffffffffffffffffffffffffffffffffffff166005856040518060400160405280600281526020017f5b5d0000000000000000000000000000000000000000000000000000000000008152506040516024016128999392919061425a565b6040516020818303038152906040527f44d227ae000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161292391906142de565b5f60405180830381855af49150503d805f811461295b576040519150601f19603f3d011682016040523d82523d5f602084013e612960565b606091505b5091509150816129a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299c9061433e565b60405180910390fd5b8092505050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a0b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612a0157612a00614197565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612a48576d04ee2d6d415b85acef81000000008381612a3e57612a3d614197565b5b0492506020810190505b662386f26fc100008310612a7757662386f26fc100008381612a6d57612a6c614197565b5b0492506010810190505b6305f5e1008310612aa0576305f5e1008381612a9657612a95614197565b5b0492506008810190505b6127108310612ac5576127108381612abb57612aba614197565b5b0492506004810190505b60648310612ae85760648381612ade57612add614197565b5b0492506002810190505b600a8310612af7576001810190505b80915050919050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612b3a82612b11565b9050919050565b612b4a81612b30565b8114612b54575f80fd5b50565b5f81359050612b6581612b41565b92915050565b5f819050919050565b612b7d81612b6b565b8114612b87575f80fd5b50565b5f81359050612b9881612b74565b92915050565b5f8060408385031215612bb457612bb3612b09565b5b5f612bc185828601612b57565b9250506020612bd285828601612b8a565b9150509250929050565b612be581612b6b565b82525050565b5f602082019050612bfe5f830184612bdc565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612c3881612c04565b8114612c42575f80fd5b50565b5f81359050612c5381612c2f565b92915050565b5f60208284031215612c6e57612c6d612b09565b5b5f612c7b84828501612c45565b91505092915050565b5f8115159050919050565b612c9881612c84565b82525050565b5f602082019050612cb15f830184612c8f565b92915050565b5f60208284031215612ccc57612ccb612b09565b5b5f612cd984828501612b8a565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612d2482612ce2565b612d2e8185612cec565b9350612d3e818560208601612cfc565b612d4781612d0a565b840191505092915050565b5f6020820190508181035f830152612d6a8184612d1a565b905092915050565b5f8060408385031215612d8857612d87612b09565b5b5f612d9585828601612b8a565b9250506020612da685828601612b8a565b9150509250929050565b612db981612b30565b82525050565b5f604082019050612dd25f830185612db0565b612ddf6020830184612bdc565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612e2082612d0a565b810181811067ffffffffffffffff82111715612e3f57612e3e612dea565b5b80604052505050565b5f612e51612b00565b9050612e5d8282612e17565b919050565b5f67ffffffffffffffff821115612e7c57612e7b612dea565b5b602082029050602081019050919050565b5f80fd5b5f612ea3612e9e84612e62565b612e48565b90508083825260208201905060208402830185811115612ec657612ec5612e8d565b5b835b81811015612eef5780612edb8882612b8a565b845260208401935050602081019050612ec8565b5050509392505050565b5f82601f830112612f0d57612f0c612de6565b5b8135612f1d848260208601612e91565b91505092915050565b5f80fd5b5f67ffffffffffffffff821115612f4457612f43612dea565b5b612f4d82612d0a565b9050602081019050919050565b828183375f83830152505050565b5f612f7a612f7584612f2a565b612e48565b905082815260208101848484011115612f9657612f95612f26565b5b612fa1848285612f5a565b509392505050565b5f82601f830112612fbd57612fbc612de6565b5b8135612fcd848260208601612f68565b91505092915050565b5f805f805f60a08688031215612fef57612fee612b09565b5b5f612ffc88828901612b57565b955050602061300d88828901612b57565b945050604086013567ffffffffffffffff81111561302e5761302d612b0d565b5b61303a88828901612ef9565b935050606086013567ffffffffffffffff81111561305b5761305a612b0d565b5b61306788828901612ef9565b925050608086013567ffffffffffffffff81111561308857613087612b0d565b5b61309488828901612fa9565b9150509295509295909350565b5f67ffffffffffffffff8211156130bb576130ba612dea565b5b602082029050602081019050919050565b5f6130de6130d9846130a1565b612e48565b9050808382526020820190506020840283018581111561310157613100612e8d565b5b835b8181101561312a57806131168882612b57565b845260208401935050602081019050613103565b5050509392505050565b5f82601f83011261314857613147612de6565b5b81356131588482602086016130cc565b91505092915050565b5f806040838503121561317757613176612b09565b5b5f83013567ffffffffffffffff81111561319457613193612b0d565b5b6131a085828601613134565b925050602083013567ffffffffffffffff8111156131c1576131c0612b0d565b5b6131cd85828601612ef9565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61320981612b6b565b82525050565b5f61321a8383613200565b60208301905092915050565b5f602082019050919050565b5f61323c826131d7565b61324681856131e1565b9350613251836131f1565b805f5b83811015613281578151613268888261320f565b975061327383613226565b925050600181019050613254565b5085935050505092915050565b5f6020820190508181035f8301526132a68184613232565b905092915050565b6132b781612c84565b81146132c1575f80fd5b50565b5f813590506132d2816132ae565b92915050565b5f80604083850312156132ee576132ed612b09565b5b5f6132fb85828601612b57565b925050602061330c858286016132c4565b9150509250929050565b5f819050919050565b5f61333961333461332f84612b11565b613316565b612b11565b9050919050565b5f61334a8261331f565b9050919050565b5f61335b82613340565b9050919050565b61336b81613351565b82525050565b5f6020820190506133845f830184613362565b92915050565b5f61339482613340565b9050919050565b6133a48161338a565b82525050565b5f6020820190506133bd5f83018461339b565b92915050565b5f80604083850312156133d9576133d8612b09565b5b5f6133e685828601612b57565b92505060206133f785828601612b57565b9150509250929050565b5f61340b82613340565b9050919050565b61341b81613401565b82525050565b5f6020820190506134345f830184613412565b92915050565b5f805f805f60a0868803121561345357613452612b09565b5b5f61346088828901612b57565b955050602061347188828901612b57565b945050604061348288828901612b8a565b935050606061349388828901612b8a565b925050608086013567ffffffffffffffff8111156134b4576134b3612b0d565b5b6134c088828901612fa9565b9150509295509295909350565b7f455243313135353a2063616e6e6f742071756572792062616c616e6365206f665f8201527f207a65726f206164647265737300000000000000000000000000000000000000602082015250565b5f613527602d83612cec565b9150613532826134cd565b604082019050919050565b5f6020820190508181035f8301526135548161351b565b9050919050565b5f60208201905061356e5f830184612db0565b92915050565b5f67ffffffffffffffff82111561358e5761358d612dea565b5b61359782612d0a565b9050602081019050919050565b5f6135b66135b184613574565b612e48565b9050828152602081018484840111156135d2576135d1612f26565b5b6135dd848285612cfc565b509392505050565b5f82601f8301126135f9576135f8612de6565b5b81516136098482602086016135a4565b91505092915050565b5f6020828403121561362757613626612b09565b5b5f82015167ffffffffffffffff81111561364457613643612b0d565b5b613650848285016135e5565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061369d57607f821691505b6020821081036136b0576136af613659565b5b50919050565b5f819050815f5260205f209050919050565b5f81546136d481613686565b6136de8186612cec565b9450600182165f81146136f8576001811461370e57613740565b60ff198316865281151560200286019350613740565b613717856136b6565b5f5b8381101561373857815481890152600182019150602081019050613719565b808801955050505b50505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61376d82613749565b6137778185613753565b9350613787818560208601612cfc565b61379081612d0a565b840191505092915050565b5f6040820190508181035f8301526137b381856136c8565b905081810360208301526137c78184613763565b90509392505050565b5f6137e26137dd84612f2a565b612e48565b9050828152602081018484840111156137fe576137fd612f26565b5b613809848285612cfc565b509392505050565b5f82601f83011261382557613824612de6565b5b81516138358482602086016137d0565b91505092915050565b5f6020828403121561385357613852612b09565b5b5f82015167ffffffffffffffff8111156138705761386f612b0d565b5b61387c84828501613811565b91505092915050565b7f62616c616e6365000000000000000000000000000000000000000000000000005f82015250565b5f6138b9600783612cec565b91506138c482613885565b602082019050919050565b5f6040820190508181035f8301526138e78184613763565b905081810360208301526138fa816138ad565b905092915050565b5f8151905061391081612b74565b92915050565b5f6020828403121561392b5761392a612b09565b5b5f61393884828501613902565b91505092915050565b7f746f6b656e5f75726900000000000000000000000000000000000000000000005f82015250565b5f613975600983612cec565b915061398082613941565b602082019050919050565b5f6040820190508181035f8301526139a38184613763565b905081810360208301526139b681613969565b905092915050565b7f726f79616c74795f7061796d656e7473000000000000000000000000000000005f82015250565b5f6139f2601083612cec565b91506139fd826139be565b602082019050919050565b5f6040820190508181035f830152613a208184613763565b90508181036020830152613a33816139e6565b905092915050565b7f726f79616c74795f696e666f00000000000000000000000000000000000000005f82015250565b5f613a6f600c83612cec565b9150613a7a82613a3b565b602082019050919050565b5f6020820190508181035f830152613a9c81613a63565b9050919050565b7f61646472657373000000000000000000000000000000000000000000000000005f82015250565b5f613ad7600783612cec565b9150613ae282613aa3565b602082019050919050565b5f6040820190508181035f830152613b058184613763565b90508181036020830152613b1881613acb565b905092915050565b7f726f79616c74795f616d6f756e740000000000000000000000000000000000005f82015250565b5f613b54600e83612cec565b9150613b5f82613b20565b602082019050919050565b5f6040820190508181035f830152613b828184613763565b90508181036020830152613b9581613b48565b905092915050565b5f81519050613bab81612b41565b92915050565b5f60208284031215613bc657613bc5612b09565b5b5f613bd384828501613b9d565b91505092915050565b7f455243313135353a207472616e7366657220746f20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c36602583612cec565b9150613c4182613bdc565b604082019050919050565b5f6020820190508181035f830152613c6381613c2a565b9050919050565b7f455243313135353a2063616c6c6572206973206e6f7420617070726f766564205f8201527f746f207472616e73666572000000000000000000000000000000000000000000602082015250565b5f613cc4602b83612cec565b9150613ccf82613c6a565b604082019050919050565b5f6020820190508181035f830152613cf181613cb8565b9050919050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e677468205f8201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b5f613d52602883612cec565b9150613d5d82613cf8565b604082019050919050565b5f6020820190508181035f830152613d7f81613d46565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f455243313135353a20696e73756666696369656e742062616c616e636520666f5f8201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b5f613e0d602a83612cec565b9150613e1882613db3565b604082019050919050565b5f6020820190508181035f830152613e3a81613e01565b9050919050565b5f81905092915050565b5f613e5582612ce2565b613e5f8185613e41565b9350613e6f818560208601612cfc565b80840191505092915050565b5f613e868285613e4b565b9150613e928284613e4b565b91508190509392505050565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b5f613ecf8284613e4b565b9150613eda82613e9e565b60018201915081905092915050565b5f6040820190508181035f830152613f018185613232565b90508181036020830152613f158184613232565b90509392505050565b5f60a082019050613f315f830188612db0565b613f3e6020830187612db0565b8181036040830152613f508186613232565b90508181036060830152613f648185613232565b90508181036080830152613f788184613763565b90509695505050505050565b5f81519050613f9281612c2f565b92915050565b5f60208284031215613fad57613fac612b09565b5b5f613fba84828501613f84565b91505092915050565b7f756e73616665207472616e7366657200000000000000000000000000000000005f82015250565b5f613ff7600f83612cec565b915061400282613fc3565b602082019050919050565b5f6020820190508181035f83015261402481613feb565b9050919050565b5f60408201905061403e5f830185612bdc565b61404b6020830184612bdc565b9392505050565b7f617070726f7665640000000000000000000000000000000000000000000000005f82015250565b5f614086600883612cec565b915061409182614052565b602082019050919050565b5f6040820190508181035f8301526140b48184613763565b905081810360208301526140c78161407a565b905092915050565b5f60a0820190506140e25f830188612db0565b6140ef6020830187612db0565b6140fc6040830186612bdc565b6141096060830185612bdc565b818103608083015261411b8184613763565b90509695505050505050565b7f2200000000000000000000000000000000000000000000000000000000000000815250565b5f6141588284613e4b565b915061416382614127565b60018201915081905092915050565b5f61417c82614127565b60018201915061418c8284613e4b565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f7d00000000000000000000000000000000000000000000000000000000000000815250565b5f6141f58284613e4b565b9150614200826141c4565b60018201915081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000815250565b5f61423f8261420f565b60018201915061424f8284613e4b565b915081905092915050565b5f6060820190508181035f83015261427281866136c8565b905081810360208301526142868185613763565b9050818103604083015261429a8184613763565b9050949350505050565b5f81905092915050565b5f6142b882613749565b6142c281856142a4565b93506142d2818560208601612cfc565b80840191505092915050565b5f6142e982846142ae565b915081905092915050565b7f436f736d5761736d2065786563757465206661696c65640000000000000000005f82015250565b5f614328601783612cec565b9150614333826142f4565b602082019050919050565b5f6020820190508181035f8301526143558161431c565b905091905056fe7b22657874656e73696f6e223a7b226d7367223a7b22636865636b5f726f79616c74696573223a7b7d7d7d7da2646970667358221220e27be5e561a26f5c4861dcfd661cb6009a9133ec93a4e83ca93d1e4fdb68217064736f6c63430008190033 \ No newline at end of file +608060405234801561000f575f80fd5b5060405161503e38038061503e833981810160405281019061003191906102ae565b60405180602001604052805f81525061004f8161014e60201b60201c565b50826005908161005f919061055f565b5061100260065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061100460085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160099081610135919061055f565b5080600a9081610145919061055f565b5050505061062e565b806002908161015d919061055f565b5050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101c08261017a565b810181811067ffffffffffffffff821117156101df576101de61018a565b5b80604052505050565b5f6101f1610161565b90506101fd82826101b7565b919050565b5f67ffffffffffffffff82111561021c5761021b61018a565b5b6102258261017a565b9050602081019050919050565b8281835e5f83830152505050565b5f61025261024d84610202565b6101e8565b90508281526020810184848401111561026e5761026d610176565b5b610279848285610232565b509392505050565b5f82601f83011261029557610294610172565b5b81516102a5848260208601610240565b91505092915050565b5f805f606084860312156102c5576102c461016a565b5b5f84015167ffffffffffffffff8111156102e2576102e161016e565b5b6102ee86828701610281565b935050602084015167ffffffffffffffff81111561030f5761030e61016e565b5b61031b86828701610281565b925050604084015167ffffffffffffffff81111561033c5761033b61016e565b5b61034886828701610281565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806103a057607f821691505b6020821081036103b3576103b261035c565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826103da565b61041f86836103da565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61046361045e61045984610437565b610440565b610437565b9050919050565b5f819050919050565b61047c83610449565b6104906104888261046a565b8484546103e6565b825550505050565b5f90565b6104a4610498565b6104af818484610473565b505050565b5b818110156104d2576104c75f8261049c565b6001810190506104b5565b5050565b601f821115610517576104e8816103b9565b6104f1846103cb565b81016020851015610500578190505b61051461050c856103cb565b8301826104b4565b50505b505050565b5f82821c905092915050565b5f6105375f198460080261051c565b1980831691505092915050565b5f61054f8383610528565b9150826002028217905092915050565b61056882610352565b67ffffffffffffffff8111156105815761058061018a565b5b61058b8254610389565b6105968282856104d6565b5f60209050601f8311600181146105c7575f84156105b5578287015190505b6105bf8582610544565b865550610626565b601f1984166105d5866103b9565b5f5b828110156105fc578489015182556001820191506020850194506020810190506105d7565b868310156106195784890151610615601f891682610528565b8355505b6001600288020188555050505b505050505050565b614a038061063b5f395ff3fe608060405234801561000f575f80fd5b5060043610610113575f3560e01c806395d89b41116100a0578063c2aed3021161006f578063c2aed30214610318578063de4725cc14610336578063e985e9c514610354578063f00b025514610384578063f242432a146103a257610113565b806395d89b4114610290578063a22cb465146102ae578063b98933a0146102ca578063bd85b039146102e857610113565b806318160ddd116100e757806318160ddd146101c55780632a55205a146101e35780632eb2c2d6146102145780634e1273f4146102305780634f558e791461026057610113565b8062fdd58e1461011757806301ffc9a71461014757806306fdde03146101775780630e89341c14610195575b5f80fd5b610131600480360381019061012c91906130d0565b6103be565b60405161013e919061311d565b60405180910390f35b610161600480360381019061015c919061318b565b61073c565b60405161016e91906131d0565b60405180910390f35b61017f6108dd565b60405161018c9190613259565b60405180910390f35b6101af60048036038101906101aa9190613279565b610969565b6040516101bc9190613259565b60405180910390f35b6101cd610b57565b6040516101da919061311d565b60405180910390f35b6101fd60048036038101906101f891906132a4565b610cce565b60405161020b9291906132f1565b60405180910390f35b61022e60048036038101906102299190613508565b6112ff565b005b61024a60048036038101906102459190613693565b611b12565b60405161025791906137c0565b60405180910390f35b61027a60048036038101906102759190613279565b611c26565b60405161028791906131d0565b60405180910390f35b610298611c39565b6040516102a59190613259565b60405180910390f35b6102c860048036038101906102c3919061380a565b611cc5565b005b6102d2611ec8565b6040516102df9190613259565b60405180910390f35b61030260048036038101906102fd9190613279565b611f54565b60405161030f919061311d565b60405180910390f35b6103206120e3565b60405161032d91906138a3565b60405180910390f35b61033e612108565b60405161034b91906138dc565b60405180910390f35b61036e600480360381019061036991906138f5565b61212d565b60405161037b91906131d0565b60405180910390f35b61038c6124d3565b6040516103999190613953565b60405180910390f35b6103bc60048036038101906103b7919061396c565b6124f8565b005b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361042d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042490613a6f565b60405180910390fd5b5f6105106040518060400160405280600581526020017f6f776e657200000000000000000000000000000000000000000000000000000081525061050b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016104c49190613a8d565b5f60405180830381865afa1580156104de573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906105069190613b44565b612b69565b612bb1565b90505f6105626040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061055d61055887612c03565b612b69565b612bb1565b90505f6105f36105ee6040518060400160405280600a81526020017f62616c616e63655f6f66000000000000000000000000000000000000000000008152506105e96105e4876040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525088612ccd565b612d1b565b612bb1565b612d1b565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401610653929190613ccd565b5f60405180830381865afa15801561066d573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906106959190613d70565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982826040518263ffffffff1660e01b81526004016106f19190613e01565b602060405180830381865afa15801561070c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107309190613e48565b94505050505092915050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061080657507fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061086e57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108d657507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600980546108ea90613bb8565b80601f016020809104026020016040519081016040528092919081815260200182805461091690613bb8565b80156109615780601f1061093857610100808354040283529160200191610961565b820191905f5260205f20905b81548152906001019060200180831161094457829003601f168201915b505050505081565b60605f6109c36109be6040518060400160405280600881526020017f746f6b656e5f69640000000000000000000000000000000000000000000000008152506109b96109b487612c03565b612b69565b612bb1565b612d1b565b90505f610a0d610a086040518060400160405280600a81526020017f746f6b656e5f696e666f0000000000000000000000000000000000000000000081525084612bb1565b612d1b565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401610a6d929190613ccd565b5f60405180830381865afa158015610a87573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610aaf9190613d70565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5826040518263ffffffff1660e01b8152600401610b0b9190613ebd565b5f60405180830381865afa158015610b25573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610b4d9190613d70565b9350505050919050565b5f8060065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d2960056040518060400160405280601181526020017f7b226e756d5f746f6b656e73223a7b7d7d0000000000000000000000000000008152506040518363ffffffff1660e01b8152600401610beb929190613ccd565b5f60405180830381865afa158015610c05573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610c2d9190613d70565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982826040518263ffffffff1660e01b8152600401610c899190613f3a565b602060405180830381865afa158015610ca4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cc89190613e48565b91505090565b5f805f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d2960056040518060600160405280602c81526020016149a2602c91396040518363ffffffff1660e01b8152600401610d46929190613ccd565b5f60405180830381865afa158015610d60573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610d889190613d70565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401610de59190613fb7565b5f60405180830381865afa158015610dff573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610e279190613d70565b90507f6273151f959616268004b58dbb21e5c851b7b8d04498b4aabee12291d22fc034818051906020012014610e92576040517f438c4bcb000000000000000000000000000000000000000000000000000000008152600401610e8990614034565b60405180910390fd5b5f610ee26040518060400160405280600881526020017f746f6b656e5f6964000000000000000000000000000000000000000000000000815250610edd610ed88a612c03565b612b69565b612bb1565b90505f610f346040518060400160405280600a81526020017f73616c655f707269636500000000000000000000000000000000000000000000815250610f2f610f2a8a612c03565b612b69565b612bb1565b90505f610fc5610fc06040518060400160405280600c81526020017f726f79616c74795f696e666f0000000000000000000000000000000000000000815250610fbb610fb687876040518060400160405280600181526020017f2c00000000000000000000000000000000000000000000000000000000000000815250612ccd565b612d1b565b612bb1565b612d1b565b90505f6110556110506040518060400160405280600981526020017f657874656e73696f6e000000000000000000000000000000000000000000000081525061104b6110466040518060400160405280600381526020017f6d7367000000000000000000000000000000000000000000000000000000000081525087612bb1565b612d1b565b612bb1565b612d1b565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b81526004016110b5929190613ccd565b5f60405180830381865afa1580156110cf573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906110f79190613d70565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166308d858e5836040518263ffffffff1660e01b8152600401611154919061409c565b5f60405180830381865afa15801561116e573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906111969190613d70565b90505f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982846040518263ffffffff1660e01b81526004016111f39190614119565b602060405180830381865afa15801561120e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112329190613e48565b90505f825103611250575f819a509a505050505050505050506112f8565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631778e539836040518263ffffffff1660e01b81526004016112aa9190613259565b602060405180830381865afa1580156112c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112e99190614160565b819a509a505050505050505050505b9250929050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361136d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611364906141fb565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113ad57506113ac853361212d565b5b6113ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e390614289565b60405180910390fd5b8151835114611430576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142790614317565b60405180910390fd5b5f5b83518110156114c85782818151811061144e5761144d614335565b5b602002602001015161147a8786848151811061146d5761146c614335565b5b60200260200101516103be565b10156114bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114b2906143d2565b60405180910390fd5b8080600101915050611432565b505f6115ac6040518060400160405280600481526020017f66726f6d000000000000000000000000000000000000000000000000000000008152506115a760085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b81526004016115609190613a8d565b5f60405180830381865afa15801561157a573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906115a29190613b44565b612b69565b612bb1565b90505f6116916040518060400160405280600281526020017f746f00000000000000000000000000000000000000000000000000000000000081525061168c60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b81526004016116459190613a8d565b5f60405180830381865afa15801561165f573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906116879190613b44565b612b69565b612bb1565b90505f6117086040518060400160405280600c81526020017f746f6b656e5f616d6f756e7400000000000000000000000000000000000000008152506040518060400160405280600181526020017f5b00000000000000000000000000000000000000000000000000000000000000815250612bb1565b90505f5b8651811015611866575f61177f6040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061177a6117758b868151811061176857611767614335565b5b6020026020010151612c03565b612b69565b612bb1565b90505f6117eb6040518060400160405280600681526020017f616d6f756e7400000000000000000000000000000000000000000000000000008152506117e66117e18b87815181106117d4576117d3614335565b5b6020026020010151612c03565b612b69565b612bb1565b905083611836611831846040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525085612ccd565b612d1b565b60405160200161184792919061442a565b604051602081830303815290604052505050808060010191505061170c565b50806040516020016118789190614473565b604051602081830303815290604052505f6119566119516040518060400160405280600a81526020017f73656e645f62617463680000000000000000000000000000000000000000000081525061194c611947886040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506119428a6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508b612ccd565b612ccd565b612d1b565b612bb1565b612d1b565b905061196181612d63565b508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8a8a6040516119d8929190614498565b60405180910390a45f8873ffffffffffffffffffffffffffffffffffffffff163b1115611b075763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168873ffffffffffffffffffffffffffffffffffffffff1663bc197c81338c8b8b8b6040518663ffffffff1660e01b8152600401611a679594939291906144cd565b6020604051808303815f875af1158015611a83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aa79190614547565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611b06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611afd906145bc565b60405180910390fd5b5b505050505050505050565b60608151835114611b5e57815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611b559291906145da565b60405180910390fd5b825167ffffffffffffffff811115611b7957611b7861331c565b5b604051908082528060200260200182016040528015611ba75781602001602082028036833780820191505090505b5090505f5b8351811015611c1f57611bf3848281518110611bcb57611bca614335565b5b6020026020010151848381518110611be657611be5614335565b5b60200260200101516103be565b828281518110611c0657611c05614335565b5b6020026020010181815250508080600101915050611bac565b5092915050565b5f80611c3183611f54565b119050919050565b600a8054611c4690613bb8565b80601f0160208091040260200160405190810160405280929190818152602001828054611c7290613bb8565b8015611cbd5780601f10611c9457610100808354040283529160200191611cbd565b820191905f5260205f20905b815481529060010190602001808311611ca057829003601f168201915b505050505081565b5f611db0611dab6040518060400160405280600881526020017f6f70657261746f72000000000000000000000000000000000000000000000000815250611da660085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b8152600401611d5f9190613a8d565b5f60405180830381865afa158015611d79573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611da19190613b44565b612b69565b612bb1565b612d1b565b90508115611e0d57611e07611e02611dfd6040518060400160405280600b81526020017f617070726f76655f616c6c00000000000000000000000000000000000000000081525084612bb1565b612d1b565b612d63565b50611e5e565b611e5c611e57611e526040518060400160405280600a81526020017f7265766f6b655f616c6c0000000000000000000000000000000000000000000081525084612bb1565b612d1b565b612d63565b505b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611ebb91906131d0565b60405180910390a3505050565b60058054611ed590613bb8565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0190613bb8565b8015611f4c5780601f10611f2357610100808354040283529160200191611f4c565b820191905f5260205f20905b815481529060010190602001808311611f2f57829003601f168201915b505050505081565b5f80611f5f83612c03565b604051602001611f6f9190614627565b604051602081830303815290604052604051602001611f8e9190614672565b60405160208183030381529060405290505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b8152600401611ffd929190613ccd565b5f60405180830381865afa158015612017573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061203f9190613d70565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982826040518263ffffffff1660e01b815260040161209b9190613f3a565b602060405180830381865afa1580156120b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120da9190613e48565b92505050919050565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f806122116040518060400160405280600581526020017f6f776e657200000000000000000000000000000000000000000000000000000081525061220c60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016121c59190613a8d565b5f60405180830381865afa1580156121df573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122079190613b44565b612b69565b612bb1565b90505f6122f66040518060400160405280600881526020017f6f70657261746f720000000000000000000000000000000000000000000000008152506122f160085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed886040518263ffffffff1660e01b81526004016122aa9190613a8d565b5f60405180830381865afa1580156122c4573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122ec9190613b44565b612b69565b612bb1565b90505f6123876123826040518060400160405280601381526020017f69735f617070726f7665645f666f725f616c6c0000000000000000000000000081525061237d612378876040518060400160405280600181526020017f2c0000000000000000000000000000000000000000000000000000000000000081525088612ccd565b612d1b565b612bb1565b612d1b565b90505f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306d81d296005846040518363ffffffff1660e01b81526004016123e7929190613ccd565b5f60405180830381865afa158015612401573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906124299190613d70565b9050600160075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a558982836040518263ffffffff1660e01b815260040161248791906146e1565b602060405180830381865afa1580156124a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c69190613e48565b1494505050505092915050565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612566576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255d906141fb565b60405180910390fd5b8161257186856103be565b10156125b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a9906143d2565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806125f257506125f1853361212d565b5b612631576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262890614289565b60405180910390fd5b5f6127146040518060400160405280600481526020017f66726f6d0000000000000000000000000000000000000000000000000000000081525061270f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b81526004016126c89190613a8d565b5f60405180830381865afa1580156126e2573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061270a9190613b44565b612b69565b612bb1565b90505f6127f96040518060400160405280600281526020017f746f0000000000000000000000000000000000000000000000000000000000008152506127f460085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c3c20ed8a6040518263ffffffff1660e01b81526004016127ad9190613a8d565b5f60405180830381865afa1580156127c7573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906127ef9190613b44565b612b69565b612bb1565b90505f61284b6040518060400160405280600881526020017f746f6b656e5f696400000000000000000000000000000000000000000000000081525061284661284189612c03565b612b69565b612bb1565b90505f61289d6040518060400160405280600681526020017f616d6f756e74000000000000000000000000000000000000000000000000000081525061289861289389612c03565b612b69565b612bb1565b90505f6129ac6129a76040518060400160405280600481526020017f73656e64000000000000000000000000000000000000000000000000000000008152506129a261299d896040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506129988b6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152506129938d6040518060400160405280600181526020017f2c000000000000000000000000000000000000000000000000000000000000008152508e612ccd565b612ccd565b612ccd565b612d1b565b612bb1565b612d1b565b90506129b781612d63565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b8b604051612a2e9291906145da565b60405180910390a45f8973ffffffffffffffffffffffffffffffffffffffff163b1115612b5d5763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168973ffffffffffffffffffffffffffffffffffffffff1663f23a6e61338d8c8c8c6040518663ffffffff1660e01b8152600401612abd959493929190614714565b6020604051808303815f875af1158015612ad9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612afd9190614547565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612b5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b53906145bc565b60405180910390fd5b5b50505050505050505050565b606081604051602001612b7c9190614792565b604051602081830303815290604052604051602001612b9b91906147b7565b6040516020818303038152906040529050919050565b6060612bfb612bbf84612b69565b6040518060400160405280600181526020017f3a0000000000000000000000000000000000000000000000000000000000000081525084612ccd565b905092915050565b60605f6001612c1184612ee1565b0190505f8167ffffffffffffffff811115612c2f57612c2e61331c565b5b6040519080825280601f01601f191660200182016040528015612c615781602001600182028036833780820191505090505b5090505f82602001820190505b600115612cc2578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612cb757612cb66147dc565b5b0494505f8503612c6e575b819350505050919050565b6060838383604051602001612ce392919061442a565b604051602081830303815290604052604051602001612d0392919061442a565b60405160208183030381529060405290509392505050565b606081604051602001612d2e919061482f565b604051602081830303815290604052604051602001612d4d919061487a565b6040516020818303038152906040529050919050565b60605f8061100273ffffffffffffffffffffffffffffffffffffffff166005856040518060400160405280600281526020017f5b5d000000000000000000000000000000000000000000000000000000000000815250604051602401612dcb9392919061489f565b6040516020818303038152906040527f44d227ae000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051612e559190614923565b5f60405180830381855af49150503d805f8114612e8d576040519150601f19603f3d011682016040523d82523d5f602084013e612e92565b606091505b509150915081612ed7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ece90614983565b60405180910390fd5b8092505050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f3d577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f3357612f326147dc565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612f7a576d04ee2d6d415b85acef81000000008381612f7057612f6f6147dc565b5b0492506020810190505b662386f26fc100008310612fa957662386f26fc100008381612f9f57612f9e6147dc565b5b0492506010810190505b6305f5e1008310612fd2576305f5e1008381612fc857612fc76147dc565b5b0492506008810190505b6127108310612ff7576127108381612fed57612fec6147dc565b5b0492506004810190505b6064831061301a57606483816130105761300f6147dc565b5b0492506002810190505b600a8310613029576001810190505b80915050919050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61306c82613043565b9050919050565b61307c81613062565b8114613086575f80fd5b50565b5f8135905061309781613073565b92915050565b5f819050919050565b6130af8161309d565b81146130b9575f80fd5b50565b5f813590506130ca816130a6565b92915050565b5f80604083850312156130e6576130e561303b565b5b5f6130f385828601613089565b9250506020613104858286016130bc565b9150509250929050565b6131178161309d565b82525050565b5f6020820190506131305f83018461310e565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61316a81613136565b8114613174575f80fd5b50565b5f8135905061318581613161565b92915050565b5f602082840312156131a05761319f61303b565b5b5f6131ad84828501613177565b91505092915050565b5f8115159050919050565b6131ca816131b6565b82525050565b5f6020820190506131e35f8301846131c1565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61322b826131e9565b61323581856131f3565b9350613245818560208601613203565b61324e81613211565b840191505092915050565b5f6020820190508181035f8301526132718184613221565b905092915050565b5f6020828403121561328e5761328d61303b565b5b5f61329b848285016130bc565b91505092915050565b5f80604083850312156132ba576132b961303b565b5b5f6132c7858286016130bc565b92505060206132d8858286016130bc565b9150509250929050565b6132eb81613062565b82525050565b5f6040820190506133045f8301856132e2565b613311602083018461310e565b9392505050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61335282613211565b810181811067ffffffffffffffff821117156133715761337061331c565b5b80604052505050565b5f613383613032565b905061338f8282613349565b919050565b5f67ffffffffffffffff8211156133ae576133ad61331c565b5b602082029050602081019050919050565b5f80fd5b5f6133d56133d084613394565b61337a565b905080838252602082019050602084028301858111156133f8576133f76133bf565b5b835b81811015613421578061340d88826130bc565b8452602084019350506020810190506133fa565b5050509392505050565b5f82601f83011261343f5761343e613318565b5b813561344f8482602086016133c3565b91505092915050565b5f80fd5b5f67ffffffffffffffff8211156134765761347561331c565b5b61347f82613211565b9050602081019050919050565b828183375f83830152505050565b5f6134ac6134a78461345c565b61337a565b9050828152602081018484840111156134c8576134c7613458565b5b6134d384828561348c565b509392505050565b5f82601f8301126134ef576134ee613318565b5b81356134ff84826020860161349a565b91505092915050565b5f805f805f60a086880312156135215761352061303b565b5b5f61352e88828901613089565b955050602061353f88828901613089565b945050604086013567ffffffffffffffff8111156135605761355f61303f565b5b61356c8882890161342b565b935050606086013567ffffffffffffffff81111561358d5761358c61303f565b5b6135998882890161342b565b925050608086013567ffffffffffffffff8111156135ba576135b961303f565b5b6135c6888289016134db565b9150509295509295909350565b5f67ffffffffffffffff8211156135ed576135ec61331c565b5b602082029050602081019050919050565b5f61361061360b846135d3565b61337a565b90508083825260208201905060208402830185811115613633576136326133bf565b5b835b8181101561365c57806136488882613089565b845260208401935050602081019050613635565b5050509392505050565b5f82601f83011261367a57613679613318565b5b813561368a8482602086016135fe565b91505092915050565b5f80604083850312156136a9576136a861303b565b5b5f83013567ffffffffffffffff8111156136c6576136c561303f565b5b6136d285828601613666565b925050602083013567ffffffffffffffff8111156136f3576136f261303f565b5b6136ff8582860161342b565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61373b8161309d565b82525050565b5f61374c8383613732565b60208301905092915050565b5f602082019050919050565b5f61376e82613709565b6137788185613713565b935061378383613723565b805f5b838110156137b357815161379a8882613741565b97506137a583613758565b925050600181019050613786565b5085935050505092915050565b5f6020820190508181035f8301526137d88184613764565b905092915050565b6137e9816131b6565b81146137f3575f80fd5b50565b5f81359050613804816137e0565b92915050565b5f80604083850312156138205761381f61303b565b5b5f61382d85828601613089565b925050602061383e858286016137f6565b9150509250929050565b5f819050919050565b5f61386b61386661386184613043565b613848565b613043565b9050919050565b5f61387c82613851565b9050919050565b5f61388d82613872565b9050919050565b61389d81613883565b82525050565b5f6020820190506138b65f830184613894565b92915050565b5f6138c682613872565b9050919050565b6138d6816138bc565b82525050565b5f6020820190506138ef5f8301846138cd565b92915050565b5f806040838503121561390b5761390a61303b565b5b5f61391885828601613089565b925050602061392985828601613089565b9150509250929050565b5f61393d82613872565b9050919050565b61394d81613933565b82525050565b5f6020820190506139665f830184613944565b92915050565b5f805f805f60a086880312156139855761398461303b565b5b5f61399288828901613089565b95505060206139a388828901613089565b94505060406139b4888289016130bc565b93505060606139c5888289016130bc565b925050608086013567ffffffffffffffff8111156139e6576139e561303f565b5b6139f2888289016134db565b9150509295509295909350565b7f455243313135353a2063616e6e6f742071756572792062616c616e6365206f665f8201527f207a65726f206164647265737300000000000000000000000000000000000000602082015250565b5f613a59602d836131f3565b9150613a64826139ff565b604082019050919050565b5f6020820190508181035f830152613a8681613a4d565b9050919050565b5f602082019050613aa05f8301846132e2565b92915050565b5f67ffffffffffffffff821115613ac057613abf61331c565b5b613ac982613211565b9050602081019050919050565b5f613ae8613ae384613aa6565b61337a565b905082815260208101848484011115613b0457613b03613458565b5b613b0f848285613203565b509392505050565b5f82601f830112613b2b57613b2a613318565b5b8151613b3b848260208601613ad6565b91505092915050565b5f60208284031215613b5957613b5861303b565b5b5f82015167ffffffffffffffff811115613b7657613b7561303f565b5b613b8284828501613b17565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613bcf57607f821691505b602082108103613be257613be1613b8b565b5b50919050565b5f819050815f5260205f209050919050565b5f8154613c0681613bb8565b613c1081866131f3565b9450600182165f8114613c2a5760018114613c4057613c72565b60ff198316865281151560200286019350613c72565b613c4985613be8565b5f5b83811015613c6a57815481890152600182019150602081019050613c4b565b808801955050505b50505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f613c9f82613c7b565b613ca98185613c85565b9350613cb9818560208601613203565b613cc281613211565b840191505092915050565b5f6040820190508181035f830152613ce58185613bfa565b90508181036020830152613cf98184613c95565b90509392505050565b5f613d14613d0f8461345c565b61337a565b905082815260208101848484011115613d3057613d2f613458565b5b613d3b848285613203565b509392505050565b5f82601f830112613d5757613d56613318565b5b8151613d67848260208601613d02565b91505092915050565b5f60208284031215613d8557613d8461303b565b5b5f82015167ffffffffffffffff811115613da257613da161303f565b5b613dae84828501613d43565b91505092915050565b7f62616c616e6365000000000000000000000000000000000000000000000000005f82015250565b5f613deb6007836131f3565b9150613df682613db7565b602082019050919050565b5f6040820190508181035f830152613e198184613c95565b90508181036020830152613e2c81613ddf565b905092915050565b5f81519050613e42816130a6565b92915050565b5f60208284031215613e5d57613e5c61303b565b5b5f613e6a84828501613e34565b91505092915050565b7f746f6b656e5f75726900000000000000000000000000000000000000000000005f82015250565b5f613ea76009836131f3565b9150613eb282613e73565b602082019050919050565b5f6040820190508181035f830152613ed58184613c95565b90508181036020830152613ee881613e9b565b905092915050565b7f636f756e740000000000000000000000000000000000000000000000000000005f82015250565b5f613f246005836131f3565b9150613f2f82613ef0565b602082019050919050565b5f6040820190508181035f830152613f528184613c95565b90508181036020830152613f6581613f18565b905092915050565b7f726f79616c74795f7061796d656e7473000000000000000000000000000000005f82015250565b5f613fa16010836131f3565b9150613fac82613f6d565b602082019050919050565b5f6040820190508181035f830152613fcf8184613c95565b90508181036020830152613fe281613f95565b905092915050565b7f726f79616c74795f696e666f00000000000000000000000000000000000000005f82015250565b5f61401e600c836131f3565b915061402982613fea565b602082019050919050565b5f6020820190508181035f83015261404b81614012565b9050919050565b7f61646472657373000000000000000000000000000000000000000000000000005f82015250565b5f6140866007836131f3565b915061409182614052565b602082019050919050565b5f6040820190508181035f8301526140b48184613c95565b905081810360208301526140c78161407a565b905092915050565b7f726f79616c74795f616d6f756e740000000000000000000000000000000000005f82015250565b5f614103600e836131f3565b915061410e826140cf565b602082019050919050565b5f6040820190508181035f8301526141318184613c95565b90508181036020830152614144816140f7565b905092915050565b5f8151905061415a81613073565b92915050565b5f602082840312156141755761417461303b565b5b5f6141828482850161414c565b91505092915050565b7f455243313135353a207472616e7366657220746f20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f6141e56025836131f3565b91506141f08261418b565b604082019050919050565b5f6020820190508181035f830152614212816141d9565b9050919050565b7f455243313135353a2063616c6c6572206973206e6f7420617070726f766564205f8201527f746f207472616e73666572000000000000000000000000000000000000000000602082015250565b5f614273602b836131f3565b915061427e82614219565b604082019050919050565b5f6020820190508181035f8301526142a081614267565b9050919050565b7f455243313135353a2069647320616e6420616d6f756e7473206c656e677468205f8201527f6d69736d61746368000000000000000000000000000000000000000000000000602082015250565b5f6143016028836131f3565b915061430c826142a7565b604082019050919050565b5f6020820190508181035f83015261432e816142f5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f455243313135353a20696e73756666696369656e742062616c616e636520666f5f8201527f72207472616e7366657200000000000000000000000000000000000000000000602082015250565b5f6143bc602a836131f3565b91506143c782614362565b604082019050919050565b5f6020820190508181035f8301526143e9816143b0565b9050919050565b5f81905092915050565b5f614404826131e9565b61440e81856143f0565b935061441e818560208601613203565b80840191505092915050565b5f61443582856143fa565b915061444182846143fa565b91508190509392505050565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b5f61447e82846143fa565b91506144898261444d565b60018201915081905092915050565b5f6040820190508181035f8301526144b08185613764565b905081810360208301526144c48184613764565b90509392505050565b5f60a0820190506144e05f8301886132e2565b6144ed60208301876132e2565b81810360408301526144ff8186613764565b905081810360608301526145138185613764565b905081810360808301526145278184613c95565b90509695505050505050565b5f8151905061454181613161565b92915050565b5f6020828403121561455c5761455b61303b565b5b5f61456984828501614533565b91505092915050565b7f756e73616665207472616e7366657200000000000000000000000000000000005f82015250565b5f6145a6600f836131f3565b91506145b182614572565b602082019050919050565b5f6020820190508181035f8301526145d38161459a565b9050919050565b5f6040820190506145ed5f83018561310e565b6145fa602083018461310e565b9392505050565b7f7b226e756d5f746f6b656e73223a7b22746f6b656e5f6964223a220000000000815250565b5f61463182614601565b601b8201915061464182846143fa565b915081905092915050565b7f227d7d0000000000000000000000000000000000000000000000000000000000815250565b5f61467d82846143fa565b91506146888261464c565b60038201915081905092915050565b7f617070726f7665640000000000000000000000000000000000000000000000005f82015250565b5f6146cb6008836131f3565b91506146d682614697565b602082019050919050565b5f6040820190508181035f8301526146f98184613c95565b9050818103602083015261470c816146bf565b905092915050565b5f60a0820190506147275f8301886132e2565b61473460208301876132e2565b614741604083018661310e565b61474e606083018561310e565b81810360808301526147608184613c95565b90509695505050505050565b7f2200000000000000000000000000000000000000000000000000000000000000815250565b5f61479d82846143fa565b91506147a88261476c565b60018201915081905092915050565b5f6147c18261476c565b6001820191506147d182846143fa565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f7d00000000000000000000000000000000000000000000000000000000000000815250565b5f61483a82846143fa565b915061484582614809565b60018201915081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000815250565b5f61488482614854565b60018201915061489482846143fa565b915081905092915050565b5f6060820190508181035f8301526148b78186613bfa565b905081810360208301526148cb8185613c95565b905081810360408301526148df8184613c95565b9050949350505050565b5f81905092915050565b5f6148fd82613c7b565b61490781856148e9565b9350614917818560208601613203565b80840191505092915050565b5f61492e82846148f3565b915081905092915050565b7f436f736d5761736d2065786563757465206661696c65640000000000000000005f82015250565b5f61496d6017836131f3565b915061497882614939565b602082019050919050565b5f6020820190508181035f83015261499a81614961565b905091905056fe7b22657874656e73696f6e223a7b226d7367223a7b22636865636b5f726f79616c74696573223a7b7d7d7d7da2646970667358221220de610b86b94a6795098b9895a3a806232f2400c016009d3febca945d5cd0cbeb64736f6c63430008190033 \ No newline at end of file diff --git a/x/evm/artifacts/cw1155/artifacts.go b/x/evm/artifacts/cw1155/artifacts.go index 3dd91308e..c05e89917 100644 --- a/x/evm/artifacts/cw1155/artifacts.go +++ b/x/evm/artifacts/cw1155/artifacts.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" // TODO: delete ) const CurrentVersion uint16 = 1 @@ -22,8 +21,7 @@ var cachedLegacyBin []byte var cachedABI *abi.ABI func GetABI() []byte { - // bz, err := f.ReadFile("CW1155ERC1155Pointer.abi") - bz, err := f.ReadFile("../cw721/CW721ERC721Pointer.abi") // TODO: remove this line and uncomment line above + bz, err := f.ReadFile("CW1155ERC1155Pointer.abi") if err != nil { panic("failed to read CW1155ERC1155Pointer contract ABI") } @@ -46,8 +44,7 @@ func GetBin() []byte { if cachedBin != nil { return cachedBin } - // code, err := f.ReadFile("CW1155ERC1155Pointer.bin") - code, err := f.ReadFile("../cw721/CW721ERC721Pointer.bin") // TODO: remove this line and uncomment line above + code, err := f.ReadFile("CW1155ERC1155Pointer.bin") if err != nil { panic("failed to read CW1155ERC1155Pointer contract binary") } @@ -71,8 +68,7 @@ func isCodeFromBin(code []byte, bin []byte) bool { if !bytes.Equal(code[:binLen], bin) { return false } - // abi, err := Cw1155MetaData.GetAbi() - abi, err := cw721.Cw721MetaData.GetAbi() // TODO: remove this line and uncomment line above + abi, err := Cw1155MetaData.GetAbi() if err != nil { fmt.Printf("error getting metadata ABI: %s\n", err) return false diff --git a/x/evm/artifacts/cw1155/cw1155.go b/x/evm/artifacts/cw1155/cw1155.go index e7afa5b38..6753e685f 100644 --- a/x/evm/artifacts/cw1155/cw1155.go +++ b/x/evm/artifacts/cw1155/cw1155.go @@ -31,7 +31,7 @@ var ( // Cw1155MetaData contains all meta data concerning the Cw1155 contract. var Cw1155MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"Cw1155Address_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplementedOnCosmwasmContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AddrPrecompile\",\"outputs\":[{\"internalType\":\"contractIAddr\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Cw1155Address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"JsonPrecompile\",\"outputs\":[{\"internalType\":\"contractIJson\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WasmdPrecompile\",\"outputs\":[{\"internalType\":\"contractIWasmd\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"balances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"Cw1155Address_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidDefaultRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidDefaultRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numerator\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"ERC2981InvalidTokenRoyalty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC2981InvalidTokenRoyaltyReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"method\",\"type\":\"string\"}],\"name\":\"NotImplementedOnCosmwasmContract\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AddrPrecompile\",\"outputs\":[{\"internalType\":\"contractIAddr\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Cw1155Address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"JsonPrecompile\",\"outputs\":[{\"internalType\":\"contractIJson\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WasmdPrecompile\",\"outputs\":[{\"internalType\":\"contractIWasmd\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"balances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"exists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"salePrice\",\"type\":\"uint256\"}],\"name\":\"royaltyInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } // Cw1155ABI is the input ABI used to generate the binding from. @@ -366,6 +366,37 @@ func (_Cw1155 *Cw1155CallerSession) BalanceOfBatch(accounts []common.Address, id return _Cw1155.Contract.BalanceOfBatch(&_Cw1155.CallOpts, accounts, ids) } +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Cw1155 *Cw1155Caller) Exists(opts *bind.CallOpts, id *big.Int) (bool, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "exists", id) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Cw1155 *Cw1155Session) Exists(id *big.Int) (bool, error) { + return _Cw1155.Contract.Exists(&_Cw1155.CallOpts, id) +} + +// Exists is a free data retrieval call binding the contract method 0x4f558e79. +// +// Solidity: function exists(uint256 id) view returns(bool) +func (_Cw1155 *Cw1155CallerSession) Exists(id *big.Int) (bool, error) { + return _Cw1155.Contract.Exists(&_Cw1155.CallOpts, id) +} + // IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. // // Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) @@ -397,6 +428,37 @@ func (_Cw1155 *Cw1155CallerSession) IsApprovedForAll(owner common.Address, opera return _Cw1155.Contract.IsApprovedForAll(&_Cw1155.CallOpts, owner, operator) } +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Cw1155 *Cw1155Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Cw1155 *Cw1155Session) Name() (string, error) { + return _Cw1155.Contract.Name(&_Cw1155.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Cw1155 *Cw1155CallerSession) Name() (string, error) { + return _Cw1155.Contract.Name(&_Cw1155.CallOpts) +} + // RoyaltyInfo is a free data retrieval call binding the contract method 0x2a55205a. // // Solidity: function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns(address, uint256) @@ -460,6 +522,99 @@ func (_Cw1155 *Cw1155CallerSession) SupportsInterface(interfaceId [4]byte) (bool return _Cw1155.Contract.SupportsInterface(&_Cw1155.CallOpts, interfaceId) } +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Cw1155 *Cw1155Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Cw1155 *Cw1155Session) Symbol() (string, error) { + return _Cw1155.Contract.Symbol(&_Cw1155.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Cw1155 *Cw1155CallerSession) Symbol() (string, error) { + return _Cw1155.Contract.Symbol(&_Cw1155.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Cw1155 *Cw1155Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Cw1155 *Cw1155Session) TotalSupply() (*big.Int, error) { + return _Cw1155.Contract.TotalSupply(&_Cw1155.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Cw1155 *Cw1155CallerSession) TotalSupply() (*big.Int, error) { + return _Cw1155.Contract.TotalSupply(&_Cw1155.CallOpts) +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155Caller) TotalSupply0(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _Cw1155.contract.Call(opts, &out, "totalSupply0", id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155Session) TotalSupply0(id *big.Int) (*big.Int, error) { + return _Cw1155.Contract.TotalSupply0(&_Cw1155.CallOpts, id) +} + +// TotalSupply0 is a free data retrieval call binding the contract method 0xbd85b039. +// +// Solidity: function totalSupply(uint256 id) view returns(uint256) +func (_Cw1155 *Cw1155CallerSession) TotalSupply0(id *big.Int) (*big.Int, error) { + return _Cw1155.Contract.TotalSupply0(&_Cw1155.CallOpts, id) +} + // Uri is a free data retrieval call binding the contract method 0x0e89341c. // // Solidity: function uri(uint256 id) view returns(string) diff --git a/x/evm/client/wasm/bindings/queries.go b/x/evm/client/wasm/bindings/queries.go index a7a18cede..7cc165430 100644 --- a/x/evm/client/wasm/bindings/queries.go +++ b/x/evm/client/wasm/bindings/queries.go @@ -13,21 +13,35 @@ const ( ERC20ApproveType EVMQueryType = "evm_query_erc20_approve" ERC20AllowanceType EVMQueryType = "evm_query_erc20_allowance" // #nosec G101 -- the word Token triggers the credential detection - ERC20TokenInfoType EVMQueryType = "evm_query_erc20_token_info" - ERC20BalanceType EVMQueryType = "evm_query_erc20_balance" - ERC721OwnerType EVMQueryType = "evm_query_erc721_owner" - ERC721TransferType EVMQueryType = "evm_query_erc721_transfer" - ERC721ApproveType EVMQueryType = "evm_query_erc721_approve" - ERC721SetApprovalAllType EVMQueryType = "evm_query_erc721_set_approval_all" - ERC721ApprovedType EVMQueryType = "evm_query_erc721_approved" - ERC721IsApprovedForAllType EVMQueryType = "evm_query_erc721_is_approved_for_all" - ERC721TotalSupplyType EVMQueryType = "evm_query_erc721_total_supply" - ERC721NameSymbolType EVMQueryType = "evm_query_erc721_name_symbol" - ERC721UriType EVMQueryType = "evm_query_erc721_uri" - ERC721RoyaltyInfoType EVMQueryType = "evm_query_erc721_royalty_info" - GetEvmAddressType EVMQueryType = "evm_query_get_evm_address" - GetSeiAddressType EVMQueryType = "evm_query_get_sei_address" - SupportsInterfaceType EVMQueryType = "evm_query_supports_interface" + ERC20TokenInfoType EVMQueryType = "evm_query_erc20_token_info" + ERC20BalanceType EVMQueryType = "evm_query_erc20_balance" + ERC721OwnerType EVMQueryType = "evm_query_erc721_owner" + ERC721TransferType EVMQueryType = "evm_query_erc721_transfer" + ERC721ApproveType EVMQueryType = "evm_query_erc721_approve" + ERC721SetApprovalAllType EVMQueryType = "evm_query_erc721_set_approval_all" + ERC721ApprovedType EVMQueryType = "evm_query_erc721_approved" + ERC721IsApprovedForAllType EVMQueryType = "evm_query_erc721_is_approved_for_all" + ERC721TotalSupplyType EVMQueryType = "evm_query_erc721_total_supply" + ERC721NameSymbolType EVMQueryType = "evm_query_erc721_name_symbol" + ERC721UriType EVMQueryType = "evm_query_erc721_uri" + ERC721RoyaltyInfoType EVMQueryType = "evm_query_erc721_royalty_info" + ERC1155TransferType EVMQueryType = "evm_query_erc1155_transfer" + ERC1155BatchTransferType EVMQueryType = "evm_query_erc1155_batch_transfer" + ERC1155SetApprovalAllType EVMQueryType = "evm_query_erc1155_set_approval_all" + ERC1155IsApprovedForAllType EVMQueryType = "evm_query_erc1155_is_approved_for_all" + ERC1155BalanceOfType EVMQueryType = "evm_query_erc1155_balance_of" + ERC1155BalanceOfBatchType EVMQueryType = "evm_query_erc1155_balance_of_batch" + ERC1155TotalSupplyType EVMQueryType = "evm_query_erc1155_total_supply" + // #nosec G101 -- the word Token triggers the credential detection + ERC1155TotalSupplyForTokenType EVMQueryType = "evm_query_erc1155_total_supply_for_token" + // #nosec G101 -- the word Token triggers the credential detection + ERC1155TokenExistsType EVMQueryType = "evm_query_erc1155_token_exists" + ERC1155NameSymbolType EVMQueryType = "evm_query_erc1155_name_symbol" + ERC1155UriType EVMQueryType = "evm_query_erc1155_uri" + ERC1155RoyaltyInfoType EVMQueryType = "evm_query_erc1155_royalty_info" + GetEvmAddressType EVMQueryType = "evm_query_get_evm_address" + GetSeiAddressType EVMQueryType = "evm_query_get_sei_address" + SupportsInterfaceType EVMQueryType = "evm_query_supports_interface" ) func (q *SeiEVMQuery) GetQueryType() EVMQueryType { @@ -82,6 +96,42 @@ func (q *SeiEVMQuery) GetQueryType() EVMQueryType { if q.ERC721RoyaltyInfo != nil { return ERC721RoyaltyInfoType } + if q.ERC1155TransferPayload != nil { + return ERC1155TransferType + } + if q.ERC1155BatchTransferPayload != nil { + return ERC1155BatchTransferType + } + if q.ERC1155SetApprovalAllPayload != nil { + return ERC1155SetApprovalAllType + } + if q.ERC1155IsApprovedForAll != nil { + return ERC1155IsApprovedForAllType + } + if q.ERC1155BalanceOf != nil { + return ERC1155BalanceOfType + } + if q.ERC1155BalanceOfBatch != nil { + return ERC1155BalanceOfBatchType + } + if q.ERC1155TotalSupply != nil { + return ERC1155TotalSupplyType + } + if q.ERC1155TotalSupplyForToken != nil { + return ERC1155TotalSupplyForTokenType + } + if q.ERC1155TokenExists != nil { + return ERC1155TokenExistsType + } + if q.ERC1155NameSymbol != nil { + return ERC1155NameSymbolType + } + if q.ERC1155Uri != nil { + return ERC1155UriType + } + if q.ERC1155RoyaltyInfo != nil { + return ERC1155RoyaltyInfoType + } if q.GetEvmAddress != nil { return GetEvmAddressType } @@ -112,13 +162,15 @@ type SeiEVMQuery struct { ERC721NameSymbol *ERC721NameSymbolRequest `json:"erc721_name_symbol,omitempty"` ERC721Uri *ERC721UriRequest `json:"erc721_uri,omitempty"` ERC721RoyaltyInfo *ERC721RoyaltyInfoRequest `json:"erc721_royalty_info,omitempty"` - ERC1155Owner *ERC1155OwnerRequest `json:"erc1155_owner,omitempty"` - ERC1155SendBatchPayload *ERC1155TransferPayloadRequest `json:"erc1155_transfer_payload,omitempty"` - ERC1155ApprovePayload *ERC1155ApprovePayloadRequest `json:"erc1155_approve_payload,omitempty"` + ERC1155TransferPayload *ERC1155TransferPayloadRequest `json:"erc1155_transfer_payload,omitempty"` + ERC1155BatchTransferPayload *ERC1155BatchTransferPayloadRequest `json:"erc1155_batch_transfer_payload,omitempty"` ERC1155SetApprovalAllPayload *ERC1155SetApprovalAllPayloadRequest `json:"erc1155_set_approval_all_payload,omitempty"` - ERC1155Approved *ERC1155ApprovedRequest `json:"erc1155_approved,omitempty"` ERC1155IsApprovedForAll *ERC1155IsApprovedForAllRequest `json:"erc1155_is_approved_for_all,omitempty"` + ERC1155BalanceOf *ERC1155BalanceOfRequest `json:"erc1155_balance_of,omitempty"` + ERC1155BalanceOfBatch *ERC1155BalanceOfBatchRequest `json:"erc1155_balance_of_batch,omitempty"` ERC1155TotalSupply *ERC1155TotalSupplyRequest `json:"erc1155_total_supply,omitempty"` + ERC1155TotalSupplyForToken *ERC1155TotalSupplyForTokenRequest `json:"erc1155_total_supply_for_token,omitempty"` + ERC1155TokenExists *ERC1155TokenExistsRequest `json:"erc1155_token_exists,omitempty"` ERC1155NameSymbol *ERC1155NameSymbolRequest `json:"erc1155_name_symbol,omitempty"` ERC1155Uri *ERC1155UriRequest `json:"erc1155_uri,omitempty"` ERC1155RoyaltyInfo *ERC1155RoyaltyInfoRequest `json:"erc1155_royalty_info,omitempty"` @@ -223,6 +275,81 @@ type ERC721RoyaltyInfoRequest struct { SalePrice *sdk.Int `json:"sale_price"` } +type ERC1155TransferPayloadRequest struct { + From string `json:"from"` + Recipient string `json:"recipient"` + TokenID string `json:"token_id"` + Amount *sdk.Int `json:"amount"` +} + +type ERC1155BatchTransferPayloadRequest struct { + From string `json:"from"` + Recipient string `json:"recipient"` + TokenIDs []string `json:"token_ids"` + Amounts []*sdk.Int `json:"amounts"` +} + +type ERC1155SetApprovalAllPayloadRequest struct { + To string `json:"to"` + Approved bool `json:"approved"` +} + +type ERC1155IsApprovedForAllRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + Owner string `json:"owner"` + Operator string `json:"operator"` +} + +type ERC1155BalanceOfRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + Account string `json:"account"` + TokenID string `json:"token_id"` +} + +type ERC1155BalanceOfBatchRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + Accounts []string `json:"accounts"` + TokenIDs []string `json:"token_ids"` +} + +type ERC1155TotalSupplyRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` +} + +type ERC1155TotalSupplyForTokenRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + TokenID string `json:"token_id"` +} + +type ERC1155TokenExistsRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + TokenID string `json:"token_id"` +} + +type ERC1155NameSymbolRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` +} + +type ERC1155UriRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + TokenID string `json:"token_id"` +} + +type ERC1155RoyaltyInfoRequest struct { + Caller string `json:"caller"` + ContractAddress string `json:"contract_address"` + TokenID string `json:"token_id"` + SalePrice *sdk.Int `json:"sale_price"` +} + type GetEvmAddressRequest struct { SeiAddress string `json:"sei_address"` } @@ -290,6 +417,44 @@ type ERC721RoyaltyInfoResponse struct { RoyaltyAmount *sdk.Int `json:"royalty_amount"` } +type ERC1155IsApprovedForAllResponse struct { + IsApproved bool `json:"is_approved"` +} + +type ERC1155BalanceOfResponse struct { + Balance *sdk.Int `json:"balance"` +} + +type ERC1155BalanceOfBatchResponse struct { + Balances []*sdk.Int `json:"balances"` +} + +type ERC1155TotalSupplyResponse struct { + Supply *sdk.Int `json:"supply"` +} + +type ERC1155TotalSupplyForTokenResponse struct { + Supply *sdk.Int `json:"supply"` +} + +type ERC1155TokenExistsResponse struct { + Exists bool `json:"exists"` +} + +type ERC1155NameSymbolResponse struct { + Name string `json:"name"` + Symbol string `json:"symbol"` +} + +type ERC1155UriResponse struct { + Uri string `json:"uri"` +} + +type ERC1155RoyaltyInfoResponse struct { + Receiver string `json:"receiver"` + RoyaltyAmount *sdk.Int `json:"royalty_amount"` +} + type GetEvmAddressResponse struct { EvmAddress string `json:"evm_address"` Associated bool `json:"associated"` diff --git a/x/evm/client/wasm/query.go b/x/evm/client/wasm/query.go index 6258fb22f..5900707fc 100644 --- a/x/evm/client/wasm/query.go +++ b/x/evm/client/wasm/query.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/artifacts/native" "github.com/sei-protocol/sei-chain/x/evm/client/wasm/bindings" "github.com/sei-protocol/sei-chain/x/evm/keeper" @@ -516,34 +517,420 @@ func (h *EVMQueryHandler) HandleERC721Uri(ctx sdk.Context, caller string, contra return json.Marshal(response) } -func (h *EVMQueryHandler) HandleGetEvmAddress(ctx sdk.Context, seiAddr string) ([]byte, error) { - addr, err := sdk.AccAddressFromBech32(seiAddr) +func (h *EVMQueryHandler) HandleERC721RoyaltyInfo(ctx sdk.Context, caller string, contractAddress string, tokenId string, salePrice *sdk.Int) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) if err != nil { return nil, err } - evmAddr, associated := h.k.GetEVMAddress(ctx, addr) - response := bindings.GetEvmAddressResponse{EvmAddress: evmAddr.Hex(), Associated: associated} + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC721, must be a big Int") + } + contract := common.HexToAddress(contractAddress) + abi, err := cw721.Cw721MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("royaltyInfo", t.BigInt(), salePrice.BigInt()) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("royaltyInfo", res) + if err != nil { + return nil, err + } + + typedReceiver := typed[0].(common.Address) + receiver := "" + if (typedReceiver != common.Address{}) { + receiver = h.k.GetSeiAddressOrDefault(ctx, typedReceiver).String() + } + royaltyAmount := sdk.NewIntFromBigInt(typed[1].(*big.Int)) + response := bindings.ERC721RoyaltyInfoResponse{Receiver: receiver, RoyaltyAmount: &royaltyAmount} return json.Marshal(response) } -func (h *EVMQueryHandler) HandleGetSeiAddress(ctx sdk.Context, evmAddr string) ([]byte, error) { - addr := common.HexToAddress(evmAddr) - seiAddr, associated := h.k.GetSeiAddress(ctx, addr) - response := bindings.GetSeiAddressResponse{SeiAddress: seiAddr.String(), Associated: associated} +func (h *EVMQueryHandler) HandleERC1155TransferPayload(ctx sdk.Context, from string, recipient string, tokenId string, amount *sdk.Int) ([]byte, error) { + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + fromEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(from)) + if !found { + return nil, types.NewAssociationMissingErr(from) + } + toEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(recipient)) + if !found { + return nil, types.NewAssociationMissingErr(recipient) + } + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC721, must be a big Int") + } + bz, err := abi.Pack("safeTransferFrom", fromEvmAddr, toEvmAddr, t.BigInt(), amount.BigInt(), []byte("0x0")) + if err != nil { + return nil, err + } + res := bindings.ERCPayloadResponse{EncodedPayload: base64.StdEncoding.EncodeToString(bz)} + return json.Marshal(res) +} + +func (h *EVMQueryHandler) HandleERC1155BatchTransferPayload(ctx sdk.Context, from string, recipient string, tokenIds []string, amounts []*sdk.Int) ([]byte, error) { + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + if len(tokenIds) != len(amounts) { + return nil, errors.New("mismatched argument lenghts for tokenIds and amounts") + } + fromEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(from)) + if !found { + return nil, types.NewAssociationMissingErr(from) + } + toEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(recipient)) + if !found { + return nil, types.NewAssociationMissingErr(recipient) + } + var tIds []*big.Int + for i := 0; i < len(tokenIds); i++ { + t, ok := sdk.NewIntFromString(tokenIds[i]) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + tIds = append(tIds, t.BigInt()) + } + var tAmounts []*big.Int + for i := 0; i < len(amounts); i++ { + tAmounts = append(tAmounts, amounts[i].BigInt()) + } + bz, err := abi.Pack("safeBatchTransferFrom", fromEvmAddr, toEvmAddr, tIds, tAmounts, []byte("0x0")) + if err != nil { + return nil, err + } + res := bindings.ERCPayloadResponse{EncodedPayload: base64.StdEncoding.EncodeToString(bz)} + return json.Marshal(res) +} + +func (h *EVMQueryHandler) HandleERC1155SetApprovalAllPayload(ctx sdk.Context, to string, approved bool) ([]byte, error) { + evmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(to)) + if !found { + return nil, types.NewAssociationMissingErr(to) + } + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("setApprovalForAll", evmAddr, approved) + if err != nil { + return nil, err + } + res := bindings.ERCPayloadResponse{EncodedPayload: base64.StdEncoding.EncodeToString(bz)} + return json.Marshal(res) +} + +func (h *EVMQueryHandler) HandleERC1155IsApprovedForAll(ctx sdk.Context, caller string, contractAddress string, owner string, operator string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + ownerEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(owner)) + if !found { + return nil, types.NewAssociationMissingErr(owner) + } + operatorEvmAddr, found := h.k.GetEVMAddress(ctx, sdk.MustAccAddressFromBech32(operator)) + if !found { + return nil, types.NewAssociationMissingErr(operator) + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("isApprovedForAll", ownerEvmAddr, operatorEvmAddr) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("isApprovedForAll", res) + if err != nil { + return nil, err + } + response := bindings.ERC1155IsApprovedForAllResponse{IsApproved: typed[0].(bool)} return json.Marshal(response) } -func (h *EVMQueryHandler) HandleERC721RoyaltyInfo(ctx sdk.Context, caller string, contractAddress string, tokenId string, salePrice *sdk.Int) ([]byte, error) { +func (h *EVMQueryHandler) HandleERC1155BalanceOf(ctx sdk.Context, caller string, contractAddress string, account string, tokenId string) ([]byte, error) { callerAddr, err := sdk.AccAddressFromBech32(caller) if err != nil { return nil, err } + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + addr, err := sdk.AccAddressFromBech32(account) + if err != nil { + return nil, err + } + evmAddr, found := h.k.GetEVMAddress(ctx, addr) + if !found { + return nil, types.NewAssociationMissingErr(addr.String()) + } t, ok := sdk.NewIntFromString(tokenId) if !ok { - return nil, errors.New("invalid token ID for ERC721, must be a big Int") + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") } + contract := common.HexToAddress(contractAddress) - abi, err := cw721.Cw721MetaData.GetAbi() + bz, err := abi.Pack("balanceOf", evmAddr, t.BigInt()) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + unpacked, err := abi.Unpack("balanceOf", res) + if err != nil { + return nil, err + } + balance := sdk.NewIntFromBigInt(unpacked[0].(*big.Int)) + return json.Marshal(bindings.ERC1155BalanceOfResponse{Balance: &balance}) +} + +func (h *EVMQueryHandler) HandleERC1155BalanceOfBatch(ctx sdk.Context, caller string, contractAddress string, accounts []string, tokenIds []string) ([]byte, error) { + if len(accounts) != len(tokenIds) { + return nil, errors.New("mismatched argument lenghts for accounts and tokenIds") + } + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + contract := common.HexToAddress(contractAddress) + + var evmAddrs []common.Address + for i := 0; i < len(accounts); i++ { + addr, err := sdk.AccAddressFromBech32(accounts[i]) + if err != nil { + return nil, err + } + evmAddr, found := h.k.GetEVMAddress(ctx, addr) + if !found { + return nil, types.NewAssociationMissingErr(addr.String()) + } + evmAddrs = append(evmAddrs, evmAddr) + } + + var tIds []*big.Int + for i := 0; i < len(tokenIds); i++ { + t, ok := sdk.NewIntFromString(tokenIds[i]) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + tIds = append(tIds, t.BigInt()) + } + + bz, err := abi.Pack("balanceOfBatch", evmAddrs, tIds) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + unpacked, err := abi.Unpack("balanceOfBatch", res) + if err != nil { + return nil, err + } + balances_res := unpacked[0].([]*big.Int) + var balances []*sdk.Int + for i := 0; i < len(balances_res); i++ { + balance := sdk.NewIntFromBigInt(balances_res[i]) + balances = append(balances, &balance) + } + return json.Marshal(bindings.ERC1155BalanceOfBatchResponse{Balances: balances}) +} + +func (h *EVMQueryHandler) HandleERC1155Uri(ctx sdk.Context, caller string, contractAddress string, tokenId string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("uri", t.BigInt()) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("uri", res) + if err != nil { + return nil, err + } + response := bindings.ERC1155UriResponse{Uri: typed[0].(string)} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleERC1155TotalSupply(ctx sdk.Context, caller string, contractAddress string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("totalSupply") + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("totalSupply", res) + if err != nil { + return nil, err + } + totalSupply := sdk.NewIntFromBigInt(typed[0].(*big.Int)) + response := bindings.ERC1155TotalSupplyResponse{Supply: &totalSupply} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleERC1155TotalSupplyForToken(ctx sdk.Context, caller string, contractAddress string, tokenId string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("totalSupply0", t.BigInt()) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("totalSupply0", res) + if err != nil { + return nil, err + } + totalSupply := sdk.NewIntFromBigInt(typed[0].(*big.Int)) + response := bindings.ERC1155TotalSupplyResponse{Supply: &totalSupply} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleERC1155TokenExists(ctx sdk.Context, caller string, contractAddress string, tokenId string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("exists", t.BigInt()) + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("exists", res) + if err != nil { + return nil, err + } + response := bindings.ERC1155TokenExistsResponse{Exists: typed[0].(bool)} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleERC1155NameSymbol(ctx sdk.Context, caller string, contractAddress string) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() + if err != nil { + return nil, err + } + bz, err := abi.Pack("name") + if err != nil { + return nil, err + } + res, err := h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err := abi.Unpack("name", res) + if err != nil { + return nil, err + } + name := typed[0].(string) + bz, err = abi.Pack("symbol") + if err != nil { + return nil, err + } + res, err = h.k.StaticCallEVM(ctx, callerAddr, &contract, bz) + if err != nil { + return nil, err + } + typed, err = abi.Unpack("symbol", res) + if err != nil { + return nil, err + } + symbol := typed[0].(string) + response := bindings.ERC1155NameSymbolResponse{Name: name, Symbol: symbol} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleERC1155RoyaltyInfo(ctx sdk.Context, caller string, contractAddress string, tokenId string, salePrice *sdk.Int) ([]byte, error) { + callerAddr, err := sdk.AccAddressFromBech32(caller) + if err != nil { + return nil, err + } + t, ok := sdk.NewIntFromString(tokenId) + if !ok { + return nil, errors.New("invalid token ID for ERC1155, must be a big Int") + } + contract := common.HexToAddress(contractAddress) + abi, err := cw1155.Cw1155MetaData.GetAbi() if err != nil { return nil, err } @@ -566,7 +953,7 @@ func (h *EVMQueryHandler) HandleERC721RoyaltyInfo(ctx sdk.Context, caller string receiver = h.k.GetSeiAddressOrDefault(ctx, typedReceiver).String() } royaltyAmount := sdk.NewIntFromBigInt(typed[1].(*big.Int)) - response := bindings.ERC721RoyaltyInfoResponse{Receiver: receiver, RoyaltyAmount: &royaltyAmount} + response := bindings.ERC1155RoyaltyInfoResponse{Receiver: receiver, RoyaltyAmount: &royaltyAmount} return json.Marshal(response) } @@ -600,3 +987,20 @@ func (h *EVMQueryHandler) HandleSupportsInterface(ctx sdk.Context, caller string } return json.Marshal(bindings.SupportsInterfaceResponse{Supported: typed[0].(bool)}) } + +func (h *EVMQueryHandler) HandleGetEvmAddress(ctx sdk.Context, seiAddr string) ([]byte, error) { + addr, err := sdk.AccAddressFromBech32(seiAddr) + if err != nil { + return nil, err + } + evmAddr, associated := h.k.GetEVMAddress(ctx, addr) + response := bindings.GetEvmAddressResponse{EvmAddress: evmAddr.Hex(), Associated: associated} + return json.Marshal(response) +} + +func (h *EVMQueryHandler) HandleGetSeiAddress(ctx sdk.Context, evmAddr string) ([]byte, error) { + addr := common.HexToAddress(evmAddr) + seiAddr, associated := h.k.GetSeiAddress(ctx, addr) + response := bindings.GetSeiAddressResponse{SeiAddress: seiAddr.String(), Associated: associated} + return json.Marshal(response) +} diff --git a/x/evm/client/wasm/query_test.go b/x/evm/client/wasm/query_test.go index 194aec2cc..807da3359 100644 --- a/x/evm/client/wasm/query_test.go +++ b/x/evm/client/wasm/query_test.go @@ -260,6 +260,194 @@ func TestHandleERC721RoyaltyInfo(t *testing.T) { require.True(t, match) } +// 1155 +func TestERC1155TransferPayload(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + addr1, e1 := testkeeper.MockAddressPair() + addr2, e2 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + k.SetAddressMapping(ctx, addr2, e2) + h := wasm.NewEVMQueryHandler(k) + value := types.NewInt(5) + res, err := h.HandleERC1155TransferPayload(ctx, addr1.String(), addr2.String(), "1", &value) + require.Nil(t, err) + require.NotEmpty(t, res) +} + +func TestERC1155BatchTransferPayload(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + addr1, e1 := testkeeper.MockAddressPair() + addr2, e2 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + k.SetAddressMapping(ctx, addr2, e2) + h := wasm.NewEVMQueryHandler(k) + value := types.NewInt(5) + res, err := h.HandleERC1155BatchTransferPayload(ctx, addr1.String(), addr2.String(), []string{"0", "1", "2"}, []*sdk.Int{&value, &value, &value}) + require.Nil(t, err) + require.NotEmpty(t, res) +} + +func TestERC1155ApproveAllPayload(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + h := wasm.NewEVMQueryHandler(k) + res, err := h.HandleERC1155SetApprovalAllPayload(ctx, addr1.String(), true) + require.Nil(t, err) + require.NotEmpty(t, res) +} + +func TestHandleERC1155IsApprovedForAll(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + addr2, e2 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + k.SetAddressMapping(ctx, addr2, e2) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155IsApprovedForAll(ctx, addr1.String(), contractAddr.String(), addr2.String(), addr2.String()) + require.Nil(t, err) + require.NotEmpty(t, res2) +} + +func TestHandleERC1155BalanceOf(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155BalanceOf(ctx, addr1.String(), contractAddr.String(), addr1.String(), "1") + require.Nil(t, err) + require.NotEmpty(t, res2) +} + +func TestHandleERC1155BalanceOfBatch(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155BalanceOfBatch(ctx, addr1.String(), contractAddr.String(), []string{addr1.String(), addr1.String()}, []string{"1", "2"}) + require.Nil(t, err) + require.NotEmpty(t, res2) + match, _ := regexp.MatchString(`{"balances":\["\d+","\d+"\]}`, string(res2)) + require.True(t, match) +} + +func TestHandleERC1155TotalSupply(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155TotalSupply(ctx, addr1.String(), contractAddr.String()) + require.Nil(t, err) + require.NotEmpty(t, res2) + require.Equal(t, "{\"supply\":\"150\"}", string(res2)) +} + +func TestHandleERC1155TotalSupplyForToken(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155TotalSupplyForToken(ctx, addr1.String(), contractAddr.String(), "4") + require.Nil(t, err) + require.NotEmpty(t, res2) + require.Equal(t, "{\"supply\":\"24\"}", string(res2)) +} + +func TestHandleERC1155TokenExists(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155TokenExists(ctx, addr1.String(), contractAddr.String(), "4") + require.Nil(t, err) + require.NotEmpty(t, res2) + require.Equal(t, "{\"exists\":true}", string(res2)) + res3, err := h.HandleERC1155TokenExists(ctx, addr1.String(), contractAddr.String(), "10") + require.Nil(t, err) + require.NotEmpty(t, res3) + require.Equal(t, "{\"exists\":false}", string(res3)) +} + +func TestHandleERC1155NameSymbol(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155NameSymbol(ctx, addr1.String(), contractAddr.String()) + require.Nil(t, err) + require.NotEmpty(t, res2) + require.Equal(t, "{\"name\":\"DummyERC1155\",\"symbol\":\"DUMMY\"}", string(res2)) +} + +func TestHandleERC1155Uri(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + res2, err := h.HandleERC1155Uri(ctx, addr1.String(), contractAddr.String(), "1") + require.Nil(t, err) + require.NotEmpty(t, res2) + require.Equal(t, "{\"uri\":\"https://example.com/{id}\"}", string(res2)) +} + +func TestHandleERC1155RoyaltyInfo(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + privKey := testkeeper.MockPrivateKey() + res, _ := deployContract(t, ctx, k, "../../../../example/contracts/erc1155/ERC1155Example.bin", privKey) + addr1, e1 := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, addr1, e1) + receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) + require.Nil(t, err) + contractAddr := common.HexToAddress(receipt.ContractAddress) + h := wasm.NewEVMQueryHandler(k) + value := types.NewInt(100) + res2, err := h.HandleERC1155RoyaltyInfo(ctx, addr1.String(), contractAddr.String(), "1", &value) + require.Nil(t, err) + require.NotEmpty(t, res2) + match, _ := regexp.MatchString(`{"receiver":"sei\w{39}","royalty_amount":"5"}`, string(res2)) + require.True(t, match) +} + func TestGetAddress(t *testing.T) { k, ctx := testkeeper.MockEVMKeeper() seiAddr1, evmAddr1 := testkeeper.MockAddressPair() @@ -309,7 +497,7 @@ func deployContract(t *testing.T, ctx sdk.Context, k *keeper.Keeper, path string require.Nil(t, err) txData := ethtypes.LegacyTx{ GasPrice: big.NewInt(1000000000000), - Gas: 2000000, + Gas: 4000000, To: nil, Value: big.NewInt(0), Data: bz, From 2cce20cc5e2cb2e834c74f5e8e75a5e727ab8456 Mon Sep 17 00:00:00 2001 From: shab Date: Mon, 1 Jul 2024 12:47:38 -0400 Subject: [PATCH 23/65] return unsupported for methods not supported in erc standard --- example/cosmwasm/cw1155/src/contract.rs | 141 +++++------------------- example/cosmwasm/cw1155/src/msg.rs | 5 - example/cosmwasm/cw1155/src/querier.rs | 29 +---- 3 files changed, 28 insertions(+), 147 deletions(-) diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index 5f5037a25..1c8ffa41e 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -39,11 +39,11 @@ pub fn execute( Cw1155RoyaltiesExecuteMsg::SendBatch { from, to, batch, msg } => { execute_send_batch(deps, info, from, to, batch, msg) } - Cw1155RoyaltiesExecuteMsg::Approve { spender, token_id, amount, expires: _ } => { - execute_approve(deps, info, spender, token_id, true) + Cw1155RoyaltiesExecuteMsg::Approve { .. } => { + execute_approve() }, - Cw1155RoyaltiesExecuteMsg::Revoke { spender, token_id, amount } => { - execute_approve(deps, info, spender, token_id, false) + Cw1155RoyaltiesExecuteMsg::Revoke { .. } => { + execute_approve() }, Cw1155RoyaltiesExecuteMsg::ApproveAll { operator, expires: _ } => { execute_approve_all(deps, info, operator, true) @@ -131,34 +131,8 @@ pub fn execute_send_batch( Ok(res) } -pub fn execute_approve( - deps: DepsMut, - info: MessageInfo, - spender: String, - token_id: String, - approved: bool, -) -> Result, ContractError> { - // todo - is this implemented in erc1155? - todo!() - // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; - // - // let querier = EvmQuerier::new(&deps.querier); - // let mut payload_spender = spender.clone(); - // let mut action = "approve"; - // if !approved { - // payload_spender = "".to_string(); - // action = "revoke"; - // } - // let payload = querier.erc1155_approve_payload(payload_spender, token_id.clone())?; - // let msg = EvmMsg::DelegateCallEvm { to: erc_addr, data: payload.encoded_payload }; - // let res = Response::new() - // .add_attribute("action", action) - // .add_attribute("token_id", token_id) - // .add_attribute("sender", info.sender) - // .add_attribute("spender", spender.clone()) - // .add_message(msg); - // - // Ok(res) +pub fn execute_approve() -> Result, ContractError> { + Err(ContractError::NotSupported {}) } pub fn execute_approve_all( @@ -218,12 +192,10 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { - // todo - is this implemented in erc1155? - todo!() + to_json_binary(&query_token_approvals()?) }, QueryMsg::AllBalances { .. } => { - // todo - is this implemented in erc1155? - todo!() + to_json_binary(&query_all_balances()?) }, QueryMsg::IsApprovedForAll { owner, operator } => to_json_binary(&query_is_approved_for_all(deps, env, owner, operator)?), QueryMsg::ApprovalsForAll { @@ -239,36 +211,20 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { - if let Some(token_id) = token_id { - // todo - is this implemented in erc1155? + if let Some(_) = token_id { return Err(ContractError::NotSupported {}) } else { to_json_binary(&query_num_tokens(deps, env)?) } }, - QueryMsg::Tokens { - owner, - start_after, - limit, - } => to_json_binary(&query_tokens( - deps, - env, - owner, - start_after, - limit, - )?), - QueryMsg::AllTokens { start_after, limit } => to_json_binary(&query_all_tokens( - deps, - env, - start_after, - limit, - )?), + QueryMsg::Tokens { .. } => to_json_binary(&query_tokens()?), + QueryMsg::AllTokens { .. } => to_json_binary(&query_all_tokens()?), QueryMsg::Minter {} => to_json_binary(&query_minter()?), QueryMsg::Ownership {} => to_json_binary(&query_ownership()?), QueryMsg::ContractInfo {} => to_json_binary(&query_contract_info(deps, env)?), QueryMsg::TokenInfo { token_id } => to_json_binary(&query_nft_info(deps, env, token_id)?), - QueryMsg::AllTokenInfo { start_after, limit } => { - to_json_binary(&query_all_nft_info(deps, env)?) + QueryMsg::AllTokenInfo { .. } => { + to_json_binary(&query_all_nft_info()?) }, QueryMsg::Extension { msg } => match msg { CwErc1155QueryMsg::EvmAddress {} => { @@ -297,6 +253,14 @@ pub fn query_balance_of_batch(deps: Deps, env: Env, batch: Vec< Ok(BalanceResponse{ balance }) } +pub fn query_token_approvals() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + +pub fn query_all_balances() -> Result, ContractError> { + Err(ContractError::NotSupported {}) +} + pub fn query_is_approved_for_all(deps: Deps, env: Env, owner: String, operator: String) -> StdResult { let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; let querier = EvmQuerier::new(&deps.querier); @@ -353,67 +317,16 @@ pub fn query_nft_info( }) } -pub fn query_all_nft_info( - deps: Deps, - env: Env, - // token_id: String, -) -> StdResult> { - // todo - is this implemented in erc1155? - todo!() - // let owner_of_res = query_balance_of(deps, env.clone(), token_id.to_string())?; - // let nft_info_res = query_nft_info(deps, env, token_id)?; - // Ok(AllNftInfoResponse { - // access: owner_of_res, - // info: nft_info_res, - // }) +pub fn query_all_nft_info() -> Result, ContractError> { + Err(ContractError::NotSupported {}) } -pub fn query_tokens( - deps: Deps, - env: Env, - owner: String, - start_after: Option, - limit: Option, -) -> StdResult { - // todo - is this implemented in erc1155? - todo!() - // let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; - // let querier = EvmQuerier::new(&deps.querier); - // let num_tokens = query_num_tokens(deps, env.clone())?.count; - // let start_after_id = Int256::from_str(&start_after.unwrap_or("-1".to_string()))?; - // let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; - // - // let mut cur = Int256::zero(); - // let mut counter = 0; - // let mut tokens: Vec = vec![]; - // while counter < num_tokens && tokens.len() < limit { - // let cur_str = cur.to_string(); - // let t_owner = match querier.erc1155_balance_of( - // env.clone().contract.address.into_string(), - // erc_addr.clone(), - // cur_str.to_string(), - // ) { - // Ok(res) => res.amount, - // Err(_) => "".to_string(), - // }; - // if t_owner != "" { - // counter += 1; - // if (owner.is_empty() || t_owner == owner) && cur > start_after_id { - // tokens.push(cur_str); - // } - // } - // cur += Int256::one(); - // } - // Ok(TokensResponse { tokens }) +pub fn query_tokens() -> Result { + Err(ContractError::NotSupported {}) } -pub fn query_all_tokens( - deps: Deps, - env: Env, - start_after: Option, - limit: Option, -) -> StdResult { - query_tokens(deps, env, "".to_string(), start_after, limit) +pub fn query_all_tokens() -> Result { + query_tokens() } pub fn query_royalty_info( diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs index bdad4be37..b1f0d1051 100644 --- a/example/cosmwasm/cw1155/src/msg.rs +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -115,11 +115,6 @@ pub struct Erc1155BalanceOfResponse { pub amount: String, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct Erc1155ApprovedResponse { - pub approved: String, -} - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Erc1155IsApprovedForAllResponse { pub is_approved: bool, diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs index cdda08181..d011c0955 100644 --- a/example/cosmwasm/cw1155/src/querier.rs +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{QuerierWrapper, StdResult, Uint128}; use cw1155::OwnerToken; -use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155ApprovedResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse}; +use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse}; pub const DEFAULT_LIMIT: u32 = 10; pub const MAX_LIMIT: u32 = 30; @@ -40,18 +40,6 @@ impl<'a> EvmQuerier<'a> { self.querier.query(&request) } - pub fn erc1155_approved(&self, caller: String, contract_address: String, token_id: String) -> StdResult { - // todo - is this implemented in erc1155? - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155Approved { caller, contract_address, token_id }, - // } - // .into(); - // - // self.querier.query(&request) - } - pub fn erc1155_is_approved_for_all(&self, caller: String, contract_address: String, owner: String, operator: String) -> StdResult { let request = EvmQueryWrapper { route: Route::Evm, @@ -108,21 +96,6 @@ impl<'a> EvmQuerier<'a> { self.querier.query(&request) } - // returns base64-encoded bytes - pub fn erc1155_approve_payload(&self, spender: String, token_id: String) -> StdResult { - // todo - is this implemented in erc1155? - todo!() - // let request = EvmQueryWrapper { - // route: Route::Evm, - // query_data: EvmQuery::Erc1155ApprovePayload { - // spender, token_id, - // }, - // } - // .into(); - // - // self.querier.query(&request) - } - // returns base64-encoded bytes pub fn erc1155_set_approval_all_payload(&self, to: String, approved: bool) -> StdResult { let request = EvmQueryWrapper { From f5858a807da80d4faadca6c489acb9c67e550a4c Mon Sep 17 00:00:00 2001 From: shab Date: Mon, 1 Jul 2024 16:43:42 -0400 Subject: [PATCH 24/65] fix query BalanceOfBatch response --- example/cosmwasm/cw1155/Cargo.lock | 16 ++++++++++++++++ example/cosmwasm/cw1155/Cargo.toml | 1 + example/cosmwasm/cw1155/src/contract.rs | 17 ++++++++++++----- example/cosmwasm/cw1155/src/msg.rs | 7 +++++++ example/cosmwasm/cw1155/src/querier.rs | 10 ++++++---- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/example/cosmwasm/cw1155/Cargo.lock b/example/cosmwasm/cw1155/Cargo.lock index cef628e2b..3c0e8423d 100644 --- a/example/cosmwasm/cw1155/Cargo.lock +++ b/example/cosmwasm/cw1155/Cargo.lock @@ -491,6 +491,7 @@ dependencies = [ "cw2981-royalties 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools", "schemars", "serde", "thiserror", @@ -573,6 +574,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -665,6 +672,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" diff --git a/example/cosmwasm/cw1155/Cargo.toml b/example/cosmwasm/cw1155/Cargo.toml index 55e3deee9..072e064b1 100644 --- a/example/cosmwasm/cw1155/Cargo.toml +++ b/example/cosmwasm/cw1155/Cargo.toml @@ -22,6 +22,7 @@ cw1155 = { git = "https://github.com/palletexchange/cw-nfts.git", rev = "3751bf6 cw2981-royalties = "0.18.0" cw721 = "0.18.0" cw721-base = "0.18.0" +itertools = "0.13" schemars = "0.8.16" serde = "1.0.195" thiserror = "1.0.56" \ No newline at end of file diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index 1c8ffa41e..bac5cb600 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{DepsMut, Deps, Env, MessageInfo, Response, Binary, StdResult, to_json_binary, Uint128, StdError}; +use cosmwasm_std::{DepsMut, Deps, Env, MessageInfo, Response, Binary, StdResult, to_json_binary, Uint128, StdError, Addr}; use cw721::{Approval, OperatorResponse, ContractInfoResponse, NftInfoResponse, AllNftInfoResponse, TokensResponse, OperatorsResponse, NumTokensResponse}; use cw2981_royalties::msg::{RoyaltiesInfoResponse, CheckRoyaltiesResponse}; use cw2981_royalties::{Metadata as Cw2981Metadata, Extension as Cw2981Extension}; @@ -9,8 +9,9 @@ use crate::querier::{EvmQuerier}; use crate::error::ContractError; use crate::state::ERC1155_ADDRESS; use std::str::FromStr; -use cw1155::{ApproveAllEvent, BalanceResponse, Cw1155BatchReceiveMsg, Cw1155ReceiveMsg, OwnerToken, RevokeAllEvent, TokenAmount, TransferEvent}; +use cw1155::{ApproveAllEvent, Balance, BalanceResponse, Cw1155BatchReceiveMsg, Cw1155ReceiveMsg, OwnerToken, RevokeAllEvent, TokenAmount, TransferEvent}; use cw1155_royalties::Cw1155RoyaltiesExecuteMsg; +use itertools::izip; const ERC2981_ID: &str = "0x2a55205a"; @@ -246,11 +247,17 @@ pub fn query_balance_of(deps: Deps, env: Env, owner: String, to Ok(BalanceResponse{ balance }) } -pub fn query_balance_of_batch(deps: Deps, env: Env, batch: Vec) -> StdResult { +pub fn query_balance_of_batch(deps: Deps, env: Env, batch: Vec) -> StdResult> { let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; let querier = EvmQuerier::new(&deps.querier); - let balance = Uint128::from_str(&querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, batch)?.amount)?; - Ok(BalanceResponse{ balance }) + let res = querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, batch)?; + let balances = izip!(&res.accounts, &res.token_ids, &res.amounts) + .map(|(account, token_id, amount)| Ok(Balance{ + token_id: token_id.to_string(), + owner: Addr::unchecked(account), + amount: Uint128::from_str(amount)?, + })).collect::>>()?; + Ok(balances) } pub fn query_token_approvals() -> Result, ContractError> { diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs index b1f0d1051..2e90e9820 100644 --- a/example/cosmwasm/cw1155/src/msg.rs +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -115,6 +115,13 @@ pub struct Erc1155BalanceOfResponse { pub amount: String, } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Erc1155BalanceOfBatchResponse { + pub accounts: Vec, + pub token_ids: Vec, + pub amounts: Vec, +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Erc1155IsApprovedForAllResponse { pub is_approved: bool, diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs index d011c0955..ff51de4dd 100644 --- a/example/cosmwasm/cw1155/src/querier.rs +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{QuerierWrapper, StdResult, Uint128}; use cw1155::OwnerToken; -use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse}; +use crate::msg::{Route, EvmQuery, EvmQueryWrapper, ErcPayloadResponse, Erc1155BalanceOfResponse, Erc1155IsApprovedForAllResponse, Erc1155NameSymbolResponse, Erc1155UriResponse, Erc1155RoyaltyInfoResponse, SupportsInterfaceResponse, Erc1155TotalSupplyResponse, Erc1155BalanceOfBatchResponse}; pub const DEFAULT_LIMIT: u32 = 10; pub const MAX_LIMIT: u32 = 30; @@ -25,14 +25,16 @@ impl<'a> EvmQuerier<'a> { self.querier.query(&request) } - pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, batch: Vec) -> StdResult { + pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, batch: Vec) -> StdResult { + let (accounts, token_ids): (Vec<_>, Vec<_>) = batch.iter().map(|ot| (ot.owner.to_string(), ot.token_id.to_string())).unzip(); + let request = EvmQueryWrapper { route: Route::Evm, query_data: EvmQuery::Erc1155BalanceOfBatch { caller, contract_address, - accounts: batch.iter().map(|ot| ot.owner.to_string()).collect(), - token_ids: batch.iter().map(|ot| ot.token_id.to_string()).collect() + accounts, + token_ids }, } .into(); From 5d0750c94a17da60cc86f0c65e8e7b794ce9f6aa Mon Sep 17 00:00:00 2001 From: davyli Date: Mon, 1 Jul 2024 18:57:31 -0400 Subject: [PATCH 25/65] Add new test files --- contracts/test/CW1155toERC1155PointerTest.js | 164 +++++++++++++++++++ contracts/test/ERC1155toCW1155PointerTest.js | 141 ++++++++++++++++ contracts/test/ERC721toCW721PointerTest.js | 6 +- contracts/test/lib.js | 47 ++++++ contracts/wasm/cw1155_base.wasm | Bin 0 -> 377590 bytes precompiles/pointer/pointer.go | 2 +- 6 files changed, 355 insertions(+), 5 deletions(-) create mode 100644 contracts/test/CW1155toERC1155PointerTest.js create mode 100644 contracts/test/ERC1155toCW1155PointerTest.js create mode 100644 contracts/wasm/cw1155_base.wasm diff --git a/contracts/test/CW1155toERC1155PointerTest.js b/contracts/test/CW1155toERC1155PointerTest.js new file mode 100644 index 000000000..bff0de460 --- /dev/null +++ b/contracts/test/CW1155toERC1155PointerTest.js @@ -0,0 +1,164 @@ +const {setupSigners, deployEvmContract, getAdmin, deployWasm, executeWasm, queryWasm, + deployErc1155PointerForCw1155, WASM, registerPointerForERC1155 +} = require("./lib"); +const {expect} = require("chai"); + +describe("CW1155 to ERC1155 Pointer", function () { + let accounts; + let erc1155; + let pointer; + let admin; + + before(async function () { + accounts = await setupSigners(await hre.ethers.getSigners()) + erc1155 = await deployEvmContract("Test1155") + admin = await getAdmin() + + pointer = await registerPointerForERC1155(await erc1155.getAddress()) + + await (await erc1155.mint(accounts[0].evmAddress, 1)).wait() + await (await erc1155.mint(accounts[1].evmAddress, 2)).wait() + await (await erc1155.mint(admin.evmAddress, 3)).wait() + + await (await erc1155.approve(accounts[1].evmAddress, 1)).wait(); + await (await erc1155.setApprovalForAll(admin.evmAddress, true)).wait(); + }) + + describe("validation", function(){ + it("should not allow a pointer to the pointer", async function(){ + try { + await deployErc1155PointerForCw1155(hre.ethers.provider, pointer, 5) + expect.fail(`Expected to be prevented from creating a pointer`); + } catch(e){ + expect(e.message).to.include("contract deployment failed"); + } + }) + }) + + describe("query", function(){ + it("should query the owner of a token", async function () { + const result = await queryWasm(pointer, "owner_of", { token_id: "1" }); + expect(result).to.deep.equal({data:{ + owner:accounts[0].seiAddress, + approvals:[ + {spender:accounts[1].seiAddress,expires:{never:{}}} + ] + }}); + }); + + it("should confirm an approval exists for a specific spender and token", async function () { + const result = await queryWasm(pointer, "approval", { token_id: "1", spender: accounts[1].seiAddress }); + expect(result).to.deep.equal({data:{ + approval:{spender:accounts[1].seiAddress, expires:{never:{}}} + }}); + }); + + it("should list all approvals for a token", async function () { + const result = await queryWasm(pointer, "approvals", { token_id: "1" }); + expect(result).to.deep.equal({data:{ + approvals:[ + {spender: accounts[1].seiAddress, expires:{never:{}}} + ]}}); + }); + + it("should verify if an operator is approved for all tokens of an owner", async function () { + const result = await queryWasm(pointer, "operator", { owner: accounts[0].seiAddress, operator: admin.seiAddress }); + expect(result).to.deep.equal({ + data: { + approval: { + spender: admin.seiAddress, + expires: {never:{}} + } + } + }); + }); + + it("should retrieve number of circulating tokens", async function () { + const result = await queryWasm(pointer, "num_tokens", {}); + expect(result).to.deep.equal({data:{count:3}}); + }); + + it("should retrieve contract information", async function () { + const result = await queryWasm(pointer, "contract_info", {}); + expect(result).to.deep.equal({data:{name:"MyNFT",symbol:"MYNFT"}}); + }); + + it("should fetch all information about an NFT", async function () { + const result = await queryWasm(pointer, "all_nft_info", { token_id: "1" }); + expect(result.data.access).to.deep.equal({ + owner: accounts[0].seiAddress, + approvals: [ + { + spender: accounts[1].seiAddress, + expires: { + never: {} + } + } + ] + }); + expect(result.data.info.token_uri).to.equal('https://sei.io/token/1'); + expect(result.data.info.extension.royalty_percentage).to.equal(5); + expect(result.data.info.extension.royalty_payment_address).to.include("sei1"); + }); + + it("should retrieve all minted NFT token ids", async function () { + const result = await queryWasm(pointer, "all_tokens", {}); + expect(result).to.deep.equal({data:{tokens:["1","2","3"]}}); + }); + + it("should retrieve list of 1 minted NFT token id after token id 1", async function () { + const result = await queryWasm(pointer, "all_tokens", { start_after: "1", limit: 1 }); + expect(result).to.deep.equal({data:{tokens:["2"]}}); + }); + + it("should retrieve list of NFT token ids owned by admin", async function () { + const result = await queryWasm(pointer, "tokens", { owner: admin.seiAddress }); + expect(result).to.deep.equal({data:{tokens:["3"]}}); + }); + }) + + describe("execute operations", function () { + it("should transfer an NFT to another address", async function () { + await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "3" }}); + const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "3" }); + expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); + await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); + const ownerResult2 = await queryWasm(pointer, "owner_of", { token_id: "3" }); + expect(ownerResult2).to.deep.equal({ data: { owner: admin.seiAddress, approvals: [] } }); + }); + + it("should not transfer an NFT if not owned", async function () { + await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "2" }}); + const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "2" }); + expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); + }); + + it("should approve a spender for a specific token", async function () { + // Approve accounts[1] to manage token ID 3 + await executeWasm(pointer, { approve: { spender: accounts[1].seiAddress, token_id: "3" }}); + const approvalResult = await queryWasm(pointer, "approval", { token_id: "3", spender: accounts[1].seiAddress }); + expect(approvalResult).to.deep.equal({ data: { approval: { spender: accounts[1].seiAddress, expires: { never: {} } } } }); + // allowed to transfer (does not revert) + await (await erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).wait(); + // transfer back to try with approval revocation (has to go back to admin first) + await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); + + // Revoke approval to reset the state + await executeWasm(pointer, { revoke: { spender: accounts[1].seiAddress, token_id: "3" }}); + const result = await queryWasm(pointer, "approvals", { token_id: "3" }); + expect(result).to.deep.equal({data: { approvals:[]}}); + + // no longer allowed to transfer + await expect(erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).to.be.revertedWith("not authorized") + }); + + it("should set an operator for all tokens of an owner", async function () { + await executeWasm(pointer, { approve_all: { operator: accounts[1].seiAddress }}); + expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.true + await executeWasm(pointer, { revoke_all: { operator: accounts[1].seiAddress }}); + expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.false; + }); + + }); + +}) \ No newline at end of file diff --git a/contracts/test/ERC1155toCW1155PointerTest.js b/contracts/test/ERC1155toCW1155PointerTest.js new file mode 100644 index 000000000..e38c51b1e --- /dev/null +++ b/contracts/test/ERC1155toCW1155PointerTest.js @@ -0,0 +1,141 @@ +const {setupSigners, deployErc1155PointerForCw1155, getAdmin, deployWasm, executeWasm, ABI, WASM, + registerPointerForERC1155 +} = require("./lib"); +const {expect} = require("chai"); + +describe("ERC1155 to CW1155 Pointer", function () { + let accounts; + let pointerAcc0; + let pointerAcc1; + let cw1155Address; + let admin; + + before(async function () { + accounts = await setupSigners(await hre.ethers.getSigners()) + admin = await getAdmin() + + cw1155Address = await deployWasm(WASM.CW1155, admin.seiAddress, "cw1155", { + name: "Test", + symbol: "TEST", + minter: admin.seiAddress + }) + + await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "1", amount: 10, token_uri: "uri1"}}}); + await executeWasm(cw1155Address, {mint: {recipient: accounts[0].seiAddress, msg: {token_id: "1", amount: 11}}}); + await executeWasm(cw1155Address, {mint: {recipient: accounts[1].seiAddress, msg: {token_id: "2", amount: 12, token_uri: "uri2"}}}); + await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "2", amount: 13}}}); + + const pointerAddr = await deployErc1155PointerForCw1155(hre.ethers.provider, cw1155Address) + const contract = new hre.ethers.Contract(pointerAddr, ABI.ERC1155, hre.ethers.provider); + pointerAcc0 = contract.connect(accounts[0].signer) + pointerAcc1 = contract.connect(accounts[1].signer) + }) + + describe("validation", function(){ + it("should not allow a pointer to the pointer", async function(){ + try { + await registerPointerForERC1155(await pointerAcc0.getAddress()) + expect.fail(`Expected to be prevented from creating a pointer`); + } catch(e){ + expect(e.message).to.include("contract deployment failed"); + } + }) + }) + + describe("read", function(){ + it("get name", async function () { + const name = await pointerAcc0.name(); + expect(name).to.equal("Test"); + }); + + it("get symbol", async function () { + const symbol = await pointerAcc0.symbol(); + expect(symbol).to.equal("TEST"); + }); + + it("owner of", async function () { + const owner = await pointerAcc0.ownerOf(1); + expect(owner).to.equal(admin.evmAddress); + }); + + it("token uri", async function () { + const uri = await pointerAcc0.uri(1); + expect(uri).to.equal("uri1"); + }); + + it("balance of", async function () { + const balance = await pointerAcc0.balanceOf(admin.evmAddress); + expect(balance).to.equal(23); + }); + + it("get approved", async function () { + const approved = await pointerAcc0.getApproved(1); + expect(approved).to.equal("0x0000000000000000000000000000000000000000"); + }); + + it("is approved for all", async function () { + const approved = await pointerAcc0.isApprovedForAll(admin.evmAddress, admin.evmAddress); + expect(approved).to.equal(false); + }); + }) + + describe("write", function(){ + it("approve", async function () { + const approvedTxResp = await pointerAcc0.approve(accounts[1].evmAddress, 2) + await approvedTxResp.wait() + const approved = await pointerAcc0.getApproved(2); + expect(approved).to.equal(accounts[1].evmAddress); + + await expect(approvedTxResp) + .to.emit(pointerAcc0, 'Approval') + .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, 2); + }); + + it("cannot approve token you don't own", async function () { + await expect(pointerAcc0.approve(accounts[1].evmAddress, 1)).to.be.reverted; + }); + + it("transfer from", async function () { + // accounts[0] should transfer token id 2 to accounts[1] + await mine(pointerAcc0.approve(accounts[1].evmAddress, 2)); + transferTxResp = await pointerAcc1.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 2); + await transferTxResp.wait(); + await expect(transferTxResp) + .to.emit(pointerAcc0, 'Transfer') + .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, 2); + const balance0 = await pointerAcc0.balanceOf(accounts[0].evmAddress); + expect(balance0).to.equal(0); + const balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress); + expect(balance1).to.equal(2); + + // return token id 2 back to accounts[0] using safe transfer from + await mine(pointerAcc1.approve(accounts[0].evmAddress, 2)); + await mine(pointerAcc1.safeTransferFrom(accounts[1].evmAddress, accounts[0].evmAddress, 2)); + const balance0After = await pointerAcc0.balanceOf(accounts[0].evmAddress); + expect(balance0After).to.equal(1); + }); + + it("cannot transfer token you don't own", async function () { + await expect(pointerAcc0.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3)).to.be.reverted; + }); + + it("set approval for all", async function () { + const setApprovalForAllTxResp = await pointerAcc0.setApprovalForAll(accounts[1].evmAddress, true); + await setApprovalForAllTxResp.wait(); + await expect(setApprovalForAllTxResp) + .to.emit(pointerAcc0, 'ApprovalForAll') + .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, true); + const approved = await pointerAcc0.isApprovedForAll(accounts[0].evmAddress, accounts[1].evmAddress); + expect(approved).to.equal(true); + + // test revoking approval + await mine(pointerAcc0.setApprovalForAll(accounts[1].evmAddress, false)); + const approvedAfter = await pointerAcc0.isApprovedForAll(accounts[0].evmAddress, accounts[1].evmAddress); + expect(approvedAfter).to.equal(false); + }); + }) +}) + +async function mine(action) { + await (await action).wait() +} diff --git a/contracts/test/ERC721toCW721PointerTest.js b/contracts/test/ERC721toCW721PointerTest.js index 3ca1fe815..fcfb2dbd9 100644 --- a/contracts/test/ERC721toCW721PointerTest.js +++ b/contracts/test/ERC721toCW721PointerTest.js @@ -1,10 +1,8 @@ -const {setupSigners, deployErc721PointerForCw721, getAdmin, deployWasm, executeWasm, ABI, registerPointerForERC20, +const {setupSigners, deployErc721PointerForCw721, getAdmin, deployWasm, executeWasm, ABI, WASM, registerPointerForERC721 } = require("./lib"); const {expect} = require("chai"); -const CW721_BASE_WASM_LOCATION = "../contracts/wasm/cw721_base.wasm"; - describe("ERC721 to CW721 Pointer", function () { let accounts; let pointerAcc0; @@ -16,7 +14,7 @@ describe("ERC721 to CW721 Pointer", function () { accounts = await setupSigners(await hre.ethers.getSigners()) admin = await getAdmin() - cw721Address = await deployWasm(CW721_BASE_WASM_LOCATION, admin.seiAddress, "cw721", { + cw721Address = await deployWasm(WASM.CW721, admin.seiAddress, "cw721", { name: "Test", symbol: "TEST", minter: admin.seiAddress diff --git a/contracts/test/lib.js b/contracts/test/lib.js index a326207ca..f75ca6b7f 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -35,9 +35,30 @@ const ABI = { "function safeTransferFrom(address from, address to, uint256 tokenId) returns (bool)", "function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) returns (bool)" ], + ERC1155: [ + "event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value)", + "event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values)", + "event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved)", + "event URI(string _value, uint256 indexed _id)", + "function name() view returns (string)", + "function symbol() view returns (string)", + "function uri(uint256 _id) view returns (string)", + "function royaltyInfo(uint256 tokenId, uint256 salePrice) view returns (address, uint256)", + "function balanceOf(address _owner, uint256 _id) view returns (uint256)", + "function balanceOfBatch(address[] _owners, uint256[] _ids) view returns (uint256[])", + "function isApprovedForAll(address _owner, address _operator) view returns (bool)", + "function setApprovalForAll(address _operator, bool _approved)", + "function transferFrom(address from, address to, uint256 tokenId) returns (bool)", + "function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes _data)", + "function safeBatchTransferFrom(address _from, address _to, uint256[] _ids, uint256[] _values, bytes _data)", + "function totalSupply() view returns (uint256)", + "function totalSupply(uint256 id) view returns (uint256);", + "function exists(uint256 id) view returns (uint256)", + ], } const WASM = { + CW1155: "../contracts/wasm/cw1155_base.wasm", CW721: "../contracts/wasm/cw721_base.wasm", CW20: "../contracts/wasm/cw20_base.wasm", POINTER_CW20: "../example/cosmwasm/cw20/artifacts/cwerc20.wasm", @@ -212,6 +233,12 @@ async function getPointerForCw721(cw721Address) { return JSON.parse(output); } +async function getPointerForCw1155(cw1155Address) { + const command = `seid query evm pointer CW1155 ${cw1155Address} -o json` + const output = await execute(command); + return JSON.parse(output); +} + async function deployErc20PointerForCw20(provider, cw20Address, attempts=10) { const command = `seid tx evm register-evm-pointer CW20 ${cw20Address} --from=admin -b block` const output = await execute(command); @@ -264,6 +291,24 @@ async function deployErc721PointerForCw721(provider, cw721Address) { throw new Error("contract deployment failed") } +async function deployErc1155PointerForCw1155(provider, cw1155Address) { + const command = `seid tx evm register-evm-pointer CW1155 ${cw1155Address} --from=admin -b block` + const output = await execute(command); + const txHash = output.replace(/.*0x/, "0x").trim() + let attempt = 0; + while(attempt < 10) { + const receipt = await provider.getTransactionReceipt(txHash); + if(receipt && receipt.status === 1) { + return (await getPointerForCw1155(cw1155Address)).pointer + } else if(receipt){ + throw new Error("contract deployment failed") + } + await sleep(500) + attempt++ + } + throw new Error("contract deployment failed") +} + async function deployWasm(path, adminAddr, label, args = {}) { const codeId = await storeWasm(path) return await instantiateWasm(codeId, adminAddr, label, args) @@ -477,8 +522,10 @@ module.exports = { deployErc20PointerForCw20, deployErc20PointerNative, deployErc721PointerForCw721, + deployErc1155PointerForCw1155, registerPointerForERC20, registerPointerForERC721, + registerPointerForERC1155, proposeCW20toERC20Upgrade, importKey, getNativeAccount, diff --git a/contracts/wasm/cw1155_base.wasm b/contracts/wasm/cw1155_base.wasm new file mode 100644 index 0000000000000000000000000000000000000000..895f6e2bf35d57e04d9df9defe3b96f953551ec2 GIT binary patch literal 377590 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 Date: Tue, 2 Jul 2024 11:09:55 -0400 Subject: [PATCH 26/65] fix Erc1155BalanceOfBatchResponse --- example/cosmwasm/cw1155/src/contract.rs | 12 ++++++------ example/cosmwasm/cw1155/src/msg.rs | 4 +--- example/cosmwasm/cw1155/src/querier.rs | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/example/cosmwasm/cw1155/src/contract.rs b/example/cosmwasm/cw1155/src/contract.rs index bac5cb600..2ee50fa21 100644 --- a/example/cosmwasm/cw1155/src/contract.rs +++ b/example/cosmwasm/cw1155/src/contract.rs @@ -250,13 +250,13 @@ pub fn query_balance_of(deps: Deps, env: Env, owner: String, to pub fn query_balance_of_batch(deps: Deps, env: Env, batch: Vec) -> StdResult> { let erc_addr = ERC1155_ADDRESS.load(deps.storage)?; let querier = EvmQuerier::new(&deps.querier); - let res = querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, batch)?; - let balances = izip!(&res.accounts, &res.token_ids, &res.amounts) - .map(|(account, token_id, amount)| Ok(Balance{ + let res = querier.erc1155_balance_of_batch(env.clone().contract.address.into_string(), erc_addr, &batch)?; + let balances = izip!(&batch, &res.amounts) + .map(|(OwnerToken{ owner, token_id }, amount)| Balance{ token_id: token_id.to_string(), - owner: Addr::unchecked(account), - amount: Uint128::from_str(amount)?, - })).collect::>>()?; + owner: Addr::unchecked(owner), + amount: amount.clone(), + }).collect(); Ok(balances) } diff --git a/example/cosmwasm/cw1155/src/msg.rs b/example/cosmwasm/cw1155/src/msg.rs index 2e90e9820..64885ffcb 100644 --- a/example/cosmwasm/cw1155/src/msg.rs +++ b/example/cosmwasm/cw1155/src/msg.rs @@ -117,9 +117,7 @@ pub struct Erc1155BalanceOfResponse { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Erc1155BalanceOfBatchResponse { - pub accounts: Vec, - pub token_ids: Vec, - pub amounts: Vec, + pub amounts: Vec, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/example/cosmwasm/cw1155/src/querier.rs b/example/cosmwasm/cw1155/src/querier.rs index ff51de4dd..1b1ec7ecc 100644 --- a/example/cosmwasm/cw1155/src/querier.rs +++ b/example/cosmwasm/cw1155/src/querier.rs @@ -25,7 +25,7 @@ impl<'a> EvmQuerier<'a> { self.querier.query(&request) } - pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, batch: Vec) -> StdResult { + pub fn erc1155_balance_of_batch(&self, caller: String, contract_address: String, batch: &Vec) -> StdResult { let (accounts, token_ids): (Vec<_>, Vec<_>) = batch.iter().map(|ot| (ot.owner.to_string(), ot.token_id.to_string())).unzip(); let request = EvmQueryWrapper { From 18768c180ad152518591a7900ef5c1c0214a2883 Mon Sep 17 00:00:00 2001 From: davyli Date: Tue, 2 Jul 2024 17:07:33 -0400 Subject: [PATCH 27/65] More testing --- contracts/src/CW1155ERC1155Pointer.sol | 38 ++- contracts/src/ERC1155.sol | 49 ++++ contracts/test/CW1155ERC1155PointerTest.t.sol | 2 +- contracts/test/CW1155toERC1155PointerTest.js | 245 +++++++++--------- contracts/test/ERC1155toCW1155PointerTest.js | 114 ++++---- contracts/test/lib.js | 2 +- contracts/wasm/cw1155_royalties.wasm | Bin 0 -> 406006 bytes ...81_royalties.wasm => cw721_royalties.wasm} | Bin example/contracts/erc1155/ERC1155Example.abi | 2 +- precompiles/wasmd/wasmd.go | 2 +- x/evm/artifacts/cw1155/artifacts.go | 4 +- x/evm/integration_test.go | 227 +++++++++++++++- 12 files changed, 491 insertions(+), 194 deletions(-) create mode 100644 contracts/src/ERC1155.sol create mode 100644 contracts/wasm/cw1155_royalties.wasm rename contracts/wasm/{cw2981_royalties.wasm => cw721_royalties.wasm} (100%) diff --git a/contracts/src/CW1155ERC1155Pointer.sol b/contracts/src/CW1155ERC1155Pointer.sol index 3f2359805..35c35a3ab 100644 --- a/contracts/src/CW1155ERC1155Pointer.sol +++ b/contracts/src/CW1155ERC1155Pointer.sol @@ -148,25 +148,35 @@ contract CW1155ERC1155Pointer is ERC1155, ERC2981 { require(to != address(0), "ERC1155: transfer to the zero address"); require(msg.sender == from || isApprovedForAll(from, msg.sender), "ERC1155: caller is not approved to transfer"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); - + require(ids.length > 0, "ERC1155: no tokens to transfer"); + address[] memory batchFrom = new address[](ids.length); for(uint256 i = 0; i < ids.length; i++){ - require(balanceOf(from, ids[i]) >= amounts[i], "ERC1155: insufficient balance for transfer"); + batchFrom[i] = from; } - - string memory f = _formatPayload("from", _doubleQuotes(AddrPrecompile.getSeiAddr(from))); - string memory t = _formatPayload("to", _doubleQuotes(AddrPrecompile.getSeiAddr(to))); - string memory tokenAmount = _formatPayload("token_amount", "["); - for(uint256 i = 0; i < ids.length; i++){ - string memory tId = _formatPayload("token_id", _doubleQuotes(Strings.toString(ids[i]))); - string memory amt = _formatPayload("amount", _doubleQuotes(Strings.toString(amounts[i]))); - string.concat(tokenAmount, _curlyBrace(_join(tId,",",amt))); + uint256[] memory balances = balanceOfBatch(batchFrom, ids); + for(uint256 i = 0; i < balances.length; i++){ + require(balances[i] >= amounts[i], "ERC1155: insufficient balance for transfer"); } - string.concat(tokenAmount, "]"); - string memory req = _curlyBrace(_formatPayload("send_batch",(_curlyBrace(_join(f,",",_join(t,",",tokenAmount)))))); - _execute(bytes(req)); + string memory payload = string.concat("{\"send_batch\":{\"from\":\"", AddrPrecompile.getSeiAddr(from)); + payload = string.concat(payload, "\",\"to\":\""); + payload = string.concat(payload, AddrPrecompile.getSeiAddr(to)); + payload = string.concat(payload, "\",\"batch\":["); + for(uint256 i = 0; i < ids.length; i++){ + string memory batch = string.concat("{\"token_id\":\"", Strings.toString(ids[i])); + batch = string.concat(batch, "\",\"amount\":\""); + batch = string.concat(batch, Strings.toString(amounts[i])); + if (i < ids.length - 1) { + batch = string.concat(batch, "\"},"); + } else { + batch = string.concat(batch, "\"}"); + } + payload = string.concat(payload, batch); + } + payload = string.concat(payload, "]}}"); + _execute(bytes(payload)); emit TransferBatch(msg.sender, from, to, ids, amounts); - if (to.code.length > 0) { + if (to.code.length > 0) { require( IERC1155Receiver(to).onERC1155BatchReceived( msg.sender, from, ids, amounts, data diff --git a/contracts/src/ERC1155.sol b/contracts/src/ERC1155.sol new file mode 100644 index 000000000..2e5084d38 --- /dev/null +++ b/contracts/src/ERC1155.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/common/ERC2981.sol"; +import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; + +contract ERC1155Example is ERC1155Supply,ERC2981 { + string public name = "DummyERC1155"; + + string public symbol = "DUMMY"; + + string private _uri = "https://example.com/{id}"; + + address private _randomAddress1 = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; + address private _randomAddress2 = 0xF39fD6e51Aad88F6f4CE6AB8827279CFffb92267; + + constructor() ERC1155(_uri) { + setDefaultRoyalty(_randomAddress1); + + mintForTest(_randomAddress1, 0); + mintForTest(_randomAddress2, 4); + } + + function mintForTest(address recipient, uint256 startId) public virtual { + uint256[] memory tids = new uint256[](6); + tids[0] = startId; + tids[1] = startId + 1; + tids[2] = startId + 2; + tids[3] = startId + 3; + tids[4] = startId + 4; + tids[5] = startId + 5; + uint256[] memory values = new uint256[](6); + values[0] = 10; + values[1] = 11; + values[2] = 12; + values[3] = 13; + values[4] = 14; + values[5] = 15; + _mintBatch(recipient, tids, values, '0x0'); + } + + function supportsInterface(bytes4 interfaceId) public view override(ERC1155, ERC2981) returns (bool) { + return super.supportsInterface(interfaceId); + } + + function setDefaultRoyalty(address receiver) public { + _setDefaultRoyalty(receiver, 500); + } +} diff --git a/contracts/test/CW1155ERC1155PointerTest.t.sol b/contracts/test/CW1155ERC1155PointerTest.t.sol index 6eb46dd18..38f96863c 100644 --- a/contracts/test/CW1155ERC1155PointerTest.t.sol +++ b/contracts/test/CW1155ERC1155PointerTest.t.sol @@ -316,7 +316,7 @@ contract CW1155ERC1155PointerTest is Test { ); vm.mockCall( WASMD_PRECOMPILE_ADDRESS, - abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"send\":{\"from\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"to\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\",\"token_id\":\"1\",\"amount\":\"1\"}}")), + abi.encodeWithSignature("execute(string,bytes,bytes)", MockCWContractAddress, bytes("{\"send\":{\"from\":\"sei19zhelek4q5lt4zam8mcarmgv92vzgqd3ux32jw\",\"to\":\"sei1vldxw5dy5k68hqr4d744rpg9w8cqs54x4asdqe\",\"batch\":[{\"token_id\":\"1\",\"amount\":\"1\"},{\"token_id\":\"2\",\"amount\":\"2\"}]}}")), abi.encode(bytes("")) ); uint256[] memory ids = new uint256[](2); diff --git a/contracts/test/CW1155toERC1155PointerTest.js b/contracts/test/CW1155toERC1155PointerTest.js index bff0de460..4caf67a40 100644 --- a/contracts/test/CW1155toERC1155PointerTest.js +++ b/contracts/test/CW1155toERC1155PointerTest.js @@ -11,16 +11,14 @@ describe("CW1155 to ERC1155 Pointer", function () { before(async function () { accounts = await setupSigners(await hre.ethers.getSigners()) - erc1155 = await deployEvmContract("Test1155") + erc1155 = await deployEvmContract("ERC1155Example") admin = await getAdmin() pointer = await registerPointerForERC1155(await erc1155.getAddress()) - await (await erc1155.mint(accounts[0].evmAddress, 1)).wait() - await (await erc1155.mint(accounts[1].evmAddress, 2)).wait() - await (await erc1155.mint(admin.evmAddress, 3)).wait() - - await (await erc1155.approve(accounts[1].evmAddress, 1)).wait(); + await (await erc1155.mintForTest(accounts[0].evmAddress, 1)).wait() + await (await erc1155.mintForTest(accounts[1].evmAddress, 2)).wait() + await (await erc1155.mintForTest(admin.evmAddress, 3)).wait() await (await erc1155.setApprovalForAll(admin.evmAddress, true)).wait(); }) @@ -36,129 +34,124 @@ describe("CW1155 to ERC1155 Pointer", function () { }) describe("query", function(){ - it("should query the owner of a token", async function () { - const result = await queryWasm(pointer, "owner_of", { token_id: "1" }); - expect(result).to.deep.equal({data:{ - owner:accounts[0].seiAddress, - approvals:[ - {spender:accounts[1].seiAddress,expires:{never:{}}} - ] - }}); - }); - - it("should confirm an approval exists for a specific spender and token", async function () { - const result = await queryWasm(pointer, "approval", { token_id: "1", spender: accounts[1].seiAddress }); - expect(result).to.deep.equal({data:{ - approval:{spender:accounts[1].seiAddress, expires:{never:{}}} - }}); - }); - - it("should list all approvals for a token", async function () { - const result = await queryWasm(pointer, "approvals", { token_id: "1" }); - expect(result).to.deep.equal({data:{ - approvals:[ - {spender: accounts[1].seiAddress, expires:{never:{}}} - ]}}); - }); - - it("should verify if an operator is approved for all tokens of an owner", async function () { - const result = await queryWasm(pointer, "operator", { owner: accounts[0].seiAddress, operator: admin.seiAddress }); - expect(result).to.deep.equal({ - data: { - approval: { - spender: admin.seiAddress, - expires: {never:{}} - } - } - }); - }); - - it("should retrieve number of circulating tokens", async function () { - const result = await queryWasm(pointer, "num_tokens", {}); - expect(result).to.deep.equal({data:{count:3}}); - }); - - it("should retrieve contract information", async function () { - const result = await queryWasm(pointer, "contract_info", {}); - expect(result).to.deep.equal({data:{name:"MyNFT",symbol:"MYNFT"}}); - }); - - it("should fetch all information about an NFT", async function () { - const result = await queryWasm(pointer, "all_nft_info", { token_id: "1" }); - expect(result.data.access).to.deep.equal({ - owner: accounts[0].seiAddress, - approvals: [ - { - spender: accounts[1].seiAddress, - expires: { - never: {} - } - } - ] - }); - expect(result.data.info.token_uri).to.equal('https://sei.io/token/1'); - expect(result.data.info.extension.royalty_percentage).to.equal(5); - expect(result.data.info.extension.royalty_payment_address).to.include("sei1"); + it("should query the balance of an owner's token", async function () { + const result = await queryWasm(pointer, "balance_of", { "owner": admin.seiAddress, token_id: "2" }); + expect(result).to.deep.equal({data:{balance:11}}); }); - it("should retrieve all minted NFT token ids", async function () { - const result = await queryWasm(pointer, "all_tokens", {}); - expect(result).to.deep.equal({data:{tokens:["1","2","3"]}}); - }); - - it("should retrieve list of 1 minted NFT token id after token id 1", async function () { - const result = await queryWasm(pointer, "all_tokens", { start_after: "1", limit: 1 }); - expect(result).to.deep.equal({data:{tokens:["2"]}}); - }); - - it("should retrieve list of NFT token ids owned by admin", async function () { - const result = await queryWasm(pointer, "tokens", { owner: admin.seiAddress }); - expect(result).to.deep.equal({data:{tokens:["3"]}}); - }); + // it("should confirm an approval exists for a specific spender and token", async function () { + // const result = await queryWasm(pointer, "is_approved_for_all", { "owner": admin.seiAddress, operator: admin.seiAddress }); + // expect(result).to.deep.equal({data:{ + // approval:{spender:accounts[1].seiAddress, expires:{never:{}}} + // }}); + // }); + + // it("should list all approvals for a token", async function () { + // const result = await queryWasm(pointer, "approvals", { token_id: "1" }); + // expect(result).to.deep.equal({data:{ + // approvals:[ + // {spender: accounts[1].seiAddress, expires:{never:{}}} + // ]}}); + // }); + + // it("should verify if an operator is approved for all tokens of an owner", async function () { + // const result = await queryWasm(pointer, "operator", { owner: accounts[0].seiAddress, operator: admin.seiAddress }); + // expect(result).to.deep.equal({ + // data: { + // approval: { + // spender: admin.seiAddress, + // expires: {never:{}} + // } + // } + // }); + // }); + + // it("should retrieve number of circulating tokens", async function () { + // const result = await queryWasm(pointer, "num_tokens", {}); + // expect(result).to.deep.equal({data:{count:3}}); + // }); + + // it("should retrieve contract information", async function () { + // const result = await queryWasm(pointer, "contract_info", {}); + // expect(result).to.deep.equal({data:{name:"MyNFT",symbol:"MYNFT"}}); + // }); + + // it("should fetch all information about an NFT", async function () { + // const result = await queryWasm(pointer, "all_nft_info", { token_id: "1" }); + // expect(result.data.access).to.deep.equal({ + // owner: accounts[0].seiAddress, + // approvals: [ + // { + // spender: accounts[1].seiAddress, + // expires: { + // never: {} + // } + // } + // ] + // }); + // expect(result.data.info.token_uri).to.equal('https://sei.io/token/1'); + // expect(result.data.info.extension.royalty_percentage).to.equal(5); + // expect(result.data.info.extension.royalty_payment_address).to.include("sei1"); + // }); + + // it("should retrieve all minted NFT token ids", async function () { + // const result = await queryWasm(pointer, "all_tokens", {}); + // expect(result).to.deep.equal({data:{tokens:["1","2","3"]}}); + // }); + + // it("should retrieve list of 1 minted NFT token id after token id 1", async function () { + // const result = await queryWasm(pointer, "all_tokens", { start_after: "1", limit: 1 }); + // expect(result).to.deep.equal({data:{tokens:["2"]}}); + // }); + + // it("should retrieve list of NFT token ids owned by admin", async function () { + // const result = await queryWasm(pointer, "tokens", { owner: admin.seiAddress }); + // expect(result).to.deep.equal({data:{tokens:["3"]}}); + // }); }) - describe("execute operations", function () { - it("should transfer an NFT to another address", async function () { - await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "3" }}); - const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "3" }); - expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); - await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); - const ownerResult2 = await queryWasm(pointer, "owner_of", { token_id: "3" }); - expect(ownerResult2).to.deep.equal({ data: { owner: admin.seiAddress, approvals: [] } }); - }); - - it("should not transfer an NFT if not owned", async function () { - await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "2" }}); - const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "2" }); - expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); - }); - - it("should approve a spender for a specific token", async function () { - // Approve accounts[1] to manage token ID 3 - await executeWasm(pointer, { approve: { spender: accounts[1].seiAddress, token_id: "3" }}); - const approvalResult = await queryWasm(pointer, "approval", { token_id: "3", spender: accounts[1].seiAddress }); - expect(approvalResult).to.deep.equal({ data: { approval: { spender: accounts[1].seiAddress, expires: { never: {} } } } }); - // allowed to transfer (does not revert) - await (await erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).wait(); - // transfer back to try with approval revocation (has to go back to admin first) - await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); - - // Revoke approval to reset the state - await executeWasm(pointer, { revoke: { spender: accounts[1].seiAddress, token_id: "3" }}); - const result = await queryWasm(pointer, "approvals", { token_id: "3" }); - expect(result).to.deep.equal({data: { approvals:[]}}); - - // no longer allowed to transfer - await expect(erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).to.be.revertedWith("not authorized") - }); - - it("should set an operator for all tokens of an owner", async function () { - await executeWasm(pointer, { approve_all: { operator: accounts[1].seiAddress }}); - expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.true - await executeWasm(pointer, { revoke_all: { operator: accounts[1].seiAddress }}); - expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.false; - }); - - }); + // describe("execute operations", function () { + // it("should transfer an NFT to another address", async function () { + // await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "3" }}); + // const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "3" }); + // expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); + // await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); + // const ownerResult2 = await queryWasm(pointer, "owner_of", { token_id: "3" }); + // expect(ownerResult2).to.deep.equal({ data: { owner: admin.seiAddress, approvals: [] } }); + // }); + + // it("should not transfer an NFT if not owned", async function () { + // await executeWasm(pointer, { transfer_nft: { recipient: accounts[1].seiAddress, token_id: "2" }}); + // const ownerResult = await queryWasm(pointer, "owner_of", { token_id: "2" }); + // expect(ownerResult).to.deep.equal({ data: { owner: accounts[1].seiAddress, approvals: [] } }); + // }); + + // it("should approve a spender for a specific token", async function () { + // // Approve accounts[1] to manage token ID 3 + // await executeWasm(pointer, { approve: { spender: accounts[1].seiAddress, token_id: "3" }}); + // const approvalResult = await queryWasm(pointer, "approval", { token_id: "3", spender: accounts[1].seiAddress }); + // expect(approvalResult).to.deep.equal({ data: { approval: { spender: accounts[1].seiAddress, expires: { never: {} } } } }); + // // allowed to transfer (does not revert) + // await (await erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).wait(); + // // transfer back to try with approval revocation (has to go back to admin first) + // await (await erc1155.connect(accounts[1].signer).transferFrom(accounts[1].evmAddress, admin.evmAddress, 3)).wait(); + + // // Revoke approval to reset the state + // await executeWasm(pointer, { revoke: { spender: accounts[1].seiAddress, token_id: "3" }}); + // const result = await queryWasm(pointer, "approvals", { token_id: "3" }); + // expect(result).to.deep.equal({data: { approvals:[]}}); + + // // no longer allowed to transfer + // await expect(erc1155.connect(accounts[1].signer).transferFrom(admin.evmAddress, accounts[1].evmAddress, 3)).to.be.revertedWith("not authorized") + // }); + + // it("should set an operator for all tokens of an owner", async function () { + // await executeWasm(pointer, { approve_all: { operator: accounts[1].seiAddress }}); + // expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.true + // await executeWasm(pointer, { revoke_all: { operator: accounts[1].seiAddress }}); + // expect(await erc1155.isApprovedForAll(admin.evmAddress, accounts[1].evmAddress)).to.be.false; + // }); + + // }); }) \ No newline at end of file diff --git a/contracts/test/ERC1155toCW1155PointerTest.js b/contracts/test/ERC1155toCW1155PointerTest.js index e38c51b1e..b2f204475 100644 --- a/contracts/test/ERC1155toCW1155PointerTest.js +++ b/contracts/test/ERC1155toCW1155PointerTest.js @@ -20,10 +20,10 @@ describe("ERC1155 to CW1155 Pointer", function () { minter: admin.seiAddress }) - await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "1", amount: 10, token_uri: "uri1"}}}); - await executeWasm(cw1155Address, {mint: {recipient: accounts[0].seiAddress, msg: {token_id: "1", amount: 11}}}); - await executeWasm(cw1155Address, {mint: {recipient: accounts[1].seiAddress, msg: {token_id: "2", amount: 12, token_uri: "uri2"}}}); - await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "2", amount: 13}}}); + await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "1", amount: "10", token_uri: "uri1"}}}); + await executeWasm(cw1155Address, {mint: {recipient: accounts[0].seiAddress, msg: {token_id: "1", amount: "11"}}}); + await executeWasm(cw1155Address, {mint: {recipient: accounts[1].seiAddress, msg: {token_id: "2", amount: "12", token_uri: "uri2"}}}); + await executeWasm(cw1155Address, {mint: {recipient: admin.seiAddress, msg: {token_id: "2", amount: "13"}}}); const pointerAddr = await deployErc1155PointerForCw1155(hre.ethers.provider, cw1155Address) const contract = new hre.ethers.Contract(pointerAddr, ABI.ERC1155, hre.ethers.provider); @@ -53,24 +53,30 @@ describe("ERC1155 to CW1155 Pointer", function () { expect(symbol).to.equal("TEST"); }); - it("owner of", async function () { - const owner = await pointerAcc0.ownerOf(1); - expect(owner).to.equal(admin.evmAddress); - }); - it("token uri", async function () { const uri = await pointerAcc0.uri(1); expect(uri).to.equal("uri1"); }); it("balance of", async function () { - const balance = await pointerAcc0.balanceOf(admin.evmAddress); - expect(balance).to.equal(23); + const balance = await pointerAcc0.balanceOf(admin.evmAddress, 1); + expect(balance).to.equal(10); }); - it("get approved", async function () { - const approved = await pointerAcc0.getApproved(1); - expect(approved).to.equal("0x0000000000000000000000000000000000000000"); + it("balance of batch", async function () { + const froms = [ + admin.evmAddress, + admin.evmAddress, + accounts[0].evmAddress, + accounts[0].evmAddress, + ]; + const tids = [1, 2, 1, 2]; + const balances = await pointerAcc0.balanceOfBatch(froms, tids); + expect(balances.length).to.equal(froms.length); + expect(balances[0]).to.equal(10); + expect(balances[1]).to.equal(13); + expect(balances[2]).to.equal(11); + expect(balances[3]).to.equal(0); }); it("is approved for all", async function () { @@ -80,43 +86,61 @@ describe("ERC1155 to CW1155 Pointer", function () { }) describe("write", function(){ - it("approve", async function () { - const approvedTxResp = await pointerAcc0.approve(accounts[1].evmAddress, 2) - await approvedTxResp.wait() - const approved = await pointerAcc0.getApproved(2); - expect(approved).to.equal(accounts[1].evmAddress); - - await expect(approvedTxResp) - .to.emit(pointerAcc0, 'Approval') - .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, 2); - }); - - it("cannot approve token you don't own", async function () { - await expect(pointerAcc0.approve(accounts[1].evmAddress, 1)).to.be.reverted; - }); - it("transfer from", async function () { - // accounts[0] should transfer token id 2 to accounts[1] - await mine(pointerAcc0.approve(accounts[1].evmAddress, 2)); - transferTxResp = await pointerAcc1.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 2); + // accounts[0] should transfer token id 1 to accounts[1] + let balance0 = await pointerAcc0.balanceOf(accounts[0].evmAddress, 1); + expect(balance0).to.equal(11); + let balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress, 1); + expect(balance1).to.equal(0); + transferTxResp = await pointerAcc1.safeTransferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 1, 5, '0x'); await transferTxResp.wait(); await expect(transferTxResp) - .to.emit(pointerAcc0, 'Transfer') - .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, 2); - const balance0 = await pointerAcc0.balanceOf(accounts[0].evmAddress); - expect(balance0).to.equal(0); - const balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress); - expect(balance1).to.equal(2); - - // return token id 2 back to accounts[0] using safe transfer from - await mine(pointerAcc1.approve(accounts[0].evmAddress, 2)); - await mine(pointerAcc1.safeTransferFrom(accounts[1].evmAddress, accounts[0].evmAddress, 2)); - const balance0After = await pointerAcc0.balanceOf(accounts[0].evmAddress); - expect(balance0After).to.equal(1); + .to.emit(pointerAcc0, 'TransferSingle') + .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, 1, 5); + balance0 = await pointerAcc0.balanceOf(accounts[0].evmAddress, 1); + expect(balance0).to.equal(6); + balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress, 1); + expect(balance1).to.equal(5); }); it("cannot transfer token you don't own", async function () { - await expect(pointerAcc0.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3)).to.be.reverted; + await expect(pointerAcc0.safeTransferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3, 1, '0x')).to.be.reverted; + }); + + it("cannot transfer token with insufficient balance", async function () { + await expect(pointerAcc0.safeTransferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 1, 100, '0x')).to.be.reverted; + }); + + it("batch transfer from", async function () { + const tids = [1, 2]; + const tamounts = [5, 4]; + let balances = await pointerAcc0.balanceOfBatch( + [admin.evmAddress, admin.evmAddress, accounts[1].evmAddress, accounts[1].evmAddress], + [...tids, ...tids] + ); + expect(balances[0]).to.equal(10); + expect(balances[1]).to.equal(13); + expect(balances[2]).to.equal(0); + expect(balances[3]).to.equal(12); + transferTxResp = await pointerAcc1.safeBatchTransferFrom( + admin.evmAddress, + accounts[1].evmAddress, + tids, + tamounts, + '0x' + ); + await transferTxResp.wait(); + await expect(transferTxResp) + .to.emit(pointerAcc0, 'TransferBatch') + .withArgs(accounts[0].evmAddress, accounts[1].evmAddress, tids, tamounts); + balances = await pointerAcc0.balanceOfBatch( + [admin.evmAddress, admin.evmAddress, accounts[1].evmAddress, accounts[1].evmAddress], + [...tids, ...tids] + ); + expect(balances[0]).to.equal(5); + expect(balances[1]).to.equal(9); + expect(balances[2]).to.equal(5); + expect(balances[3]).to.equal(16); }); it("set approval for all", async function () { diff --git a/contracts/test/lib.js b/contracts/test/lib.js index f75ca6b7f..1946912e4 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -52,7 +52,7 @@ const ABI = { "function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes _data)", "function safeBatchTransferFrom(address _from, address _to, uint256[] _ids, uint256[] _values, bytes _data)", "function totalSupply() view returns (uint256)", - "function totalSupply(uint256 id) view returns (uint256);", + "function totalSupply(uint256 id) view returns (uint256)", "function exists(uint256 id) view returns (uint256)", ], } diff --git a/contracts/wasm/cw1155_royalties.wasm b/contracts/wasm/cw1155_royalties.wasm new file mode 100644 index 0000000000000000000000000000000000000000..f94438e8cf5d0f1da9c632650a26b27a8cf1f125 GIT binary patch literal 406006 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%0DNVBg8dX?WXc)AG zhJcH~+Qgis5j(7VN1>s7BZUTrl7)tdShAr-`PE)0p`kH~%nJ=RiilfWiO|68E)p70 zAVO#uA~29FH{^wJ9HPkYh`vh@NK8CMZowcGxK;m?nS{^>Q0(bZco-aq=qs%tUgD4s zl2p?IrBO zPeA~Nr||8J)XKOx4%_4L0dnzz^W2R&+Lp^mlj98zgYh@HT$_A&pp$M7+@}L@IiCX& zp2JQmws0tE44VjcrNul@`{R^;rsMB91K0h`JyYR+vK~TTm7~wvfJ0rClP~>te;`4H zTb>N)?0^FYsF&W6?KgyHWgSjM^kG&CBnDV0h=Rm4v?^_n5gsmv>NJa7opy%3PJGYr zcxQ*+c=#iF?9NzhXG+Kxrl}eSRmN&87}Iah9h0HE6}_Rn*^c~M8~-m%vOWOm<0u?(rhOB# zga^wtYQOQ;bCQ**>cB3sgPAX6qPg6-P)YnciVXE@ckxjBd=&PB=9x$K{K zC5}a5d@6R;F>%*NZ|ihI@!?L{`8s zFip(?4)WF0Q8NwTSaUteSxtd5H>$0Lv(mg3X$5=r3)0ecR?Hm`ianAqc9YkWKjd6Z zFYm5zQ^6}u64u>HDC%QkrrrFG4vcy4(c+Mfh#}Rh(xUo^m@zME6RnS|`J0@^5-nkM zEUJAvUUe*4WS?Y_-4LxLXzY_AWH)+f^Bc8hH!n56L5khH6u&h=G(f&uU60?(A9B&s zwaBm-T~fU3FEj<}@Sxu!nS?RzQ!+$0YJnO9-VV zE1dPi@ku^zV@U!PrvbgljOb|ij_zFoq*KXFl+BJs(rHGU%`+W&bh$?&9jJd^$00qd zHpt28^N{H1@zv^P(B>AeYr1w^^IGuExk5doe@)NMx`h5Qk-4{zxs0gkDe=W=1ZP~v zJWlgDz3wM+O-?eF2E!BUB(EnWX>s5X|(fnedyx+{T;XpyoIM3~doBD?Z z%u1kNsz1voaa(=K(emYPwNyctUeXos=LKC49W7tf^@iIyd5!D!w-+zy3Me^Tl z!)Le(PW6jVZK~qWxG&H6?`cNx3dKzLo+Tcx<1F&|#k>c?EXj zBLR?vC0j2c>`XYfkqhVj!G(CWb5d*r+Tjx{jeNqs5IRtdpHfp0t)ZIITbHW!tEK&KsSskn zJpMfd4Ogw|ZlfA5Z>N4;k5PHg<9;no{d;FDY`29X?z32&HK2?5%|K((ceMw2B;vh} zyvNLX{TJqvf`O=YS1egNqe5~!OVdrQTB^|*>p+~Yy;b)-_o5^*uu>aO(??S2yXV9LObXS!Rs9Xhy! zlS)sGzrRH8USirAmO7LAOVJC3qy&p`{Mbg)I;(&4 zJTEVef1(F5zz(IUX1Sn_5?#fXdp%v|smP|0=YmT5dS5T5_ltNRETR6F^+q}VAE=;t z0UYkFez+{khr54;)vgWGR;@#Jw9yB-S!=w{;}>|`18zM@R8%?sjUx3P(e75;qJ1_B z((@5X3jI(X`aV}u-So~{9u27igj%n9;trK7oMNtE3Dlps0Dxc(JuTPn_-8m?jeEqW z9^#Ym)705DRntKn`wdFF6i=LR9Dh9UlF5K6bi(%fRcd7-dJLt0>UX$5{m;@o0DEas z^_mrN*{-boH6Wtyq*+m?24Sn1`i}d$l(qi} z61Qsuf8Y^exB*uC3FHHYBZhb2)Kr%95i8^g&pl&;*N^{kArhj=k$HixaXZqh=tm;m z(#4k&s1gyZU!ex(xvc*a*5Ze`-}vz~&jyn!yqw+#ac_4Y;vT^-awf@|Ayjly`L2k2 zZ_44U6;lbixD+KCRE)I=^6u~j=Ay-VkZ*ywmA3_5-U}T zb(p9`yvdh-WqgjcCgQ_7{x?M?x2(_sD^%-uO1(o&H)JL02}#vV)tB_dg$1j}@MJ3S zg1uF84m2><>J+05ksMtGV!7~QpH8=bnp(TJF8{om7X3t7ROLEvMJ-l+`SHu~x!w)& z9A!#o1)lNxy><6%(}%_O59=R&wex4)U1A}igfeU%f~ZO+8vq_E#KL%JiroS(;)PA# zdFtzWZDTp3BLHF`0ZH~wfy?CHM>azdj+O^v9k~>i&&sR2cyf}xR10bK(+$`$#4Kg7 zOOz3HNnn>qQw;=m1$Epb5eKkikmUwCX|OX5ltLn>*jZ*^zr?2o`~0WyhWO~-uVJ(_ z15C6vRy~Rqs{vrARA7f(^V4nS&jRdxh^V~n!whym7T6186`-?V23Gx~O*lB7S;(4f zKriYe(H;OK;VKB70c+{Xgf5Y-1a1+!8Mv32CcyohU+myUNB6P0tkZz)RRirWA|{3) z@I{Krh!Tuk=Ua$2v3v_CYd{-OXZ*iPYlO>>&Fv8{pwZ}=lwb>&)Krzyc1>rc@lCA_ zT2*Bsuv;k3>y0D|tn=}IzlA0!#foXdf&1zMSA`~|7DN(q z)tMxSDqVskATWtgWs-odC9N3;Ws+SXsEH&*S-iWDBp{nfSkQU1ev6+i*{mnoY+hK{ zDw|nY_;j~Bcz8B}gf3+c zDZLNBKmel$)~I{qXRRC_kl+?7s03i&1-ab4TA%sZ%}zb3H@J*{zr-3OYW}<2{Cd${ z(r}UgVr)As9)pY z(*r2W4C_9L*nO`usm$)BfLN8-BPifaypOL9tV;$f@Nuj_A$Dl6(p8_*hsGeVvKj)c zE$_GIKnnj>$T}cE8;hyYRI=Hqg5#O#l^-gX*kY3hO zBSG^Ut|{+$GVA%YXc=Cb-%O1x6wPmRkP?2_{Kguf_|oS05&drbK}ZK~>6oD1ymJBn znUuk%6LP3YQ)~)OV}O*CA9RyxDCPcCKk_&}%O|qrqI~~cE;DjLmj!G(w}wH zc*=V9M|_Kute5J1Lbn?(<=B{B{XyS8s@qpSpc+2JEr317;j4!W&SL(oesc>=z_Dg= zu{WjtSJIEp6r<|P{E%gDvc#3}{>fgdz{og}_RU5}M-RzN8UaZTjOo=cqbr&z?UwDT zHyJmit|43!OY3XuuIQGqe^{S+1nO}Ot9CMM-l|zfdSh9Rp5^+(dS#$jw7KSBf|_VS zz^|yVM(*bkJ!gA`E^KyClmI$7?rfC}PmTYoWmxaEfma3%gLnjG*x#aQ7^7<9c}&B& z8Tdv$&-=BYA*inhrbSp&Z46eFQ9|Rs==utO^6!X8VqKCX3kQkJf##L+JPC@TjvO@) z2z2R8=)H`n%lM$UV=4FXb^PnDx*#fcTwP}IO$CnU8~45iVY~wPUc$u6<+d~|x$>7& zcl4h8tEyyps($u+f$r4p;CA4f;dGgC0eSO|1LADvd&P_%fIlOho2=Ktoe_7}$_$7X z(M+wF9hmA~-Numh$Z})1@<6lh<`6qB>rwAlEY8Lsffv z%vGLYyD6cMxYdE0l#EIws3Crkor3^lNwdyJhtyjuB7lTD*-3|(RplENX{nV7fdG^q zVa!CA*a?k@qFVgEcw?XGPqVc|pZVRK*&5C8lE|K0GQEms1d$%#;L`ETle9?{MUmPA zvnNIEWNz-`RcTg3QoWl0K3x;Q6}e`@&I|yRgOfGArGa-maJ>oL7@p`%u4Ng>C4)Hc zRmM@3l6j~@irYX70E}Qo=cyTpoGtSN5|y}(Y-Ht~N6RC+-XYvvFWxaJRSAoRAIGPA z>NPnJx^%Lf@Mj>%dX5H~m_tJ6+lvF$;6y3cjoTIRkl-}_DMTq%l9oJ=C02nALt(>U z#u|r=ir)?E8Cc!%b5sQDjg`&2@Jp}ILpfidw0h&Ir| zPbe@XR8u`Mrp0KXO#(Ds##zqdF*5M$kjj;_!#*b6<`AdocRF;{gIZ3Y^$4zwv4W`b zInfpYD;%5ZmIcZS^4*9o9xe}@=zSds$D|*d*z`w6c|Ae4n|k`WyVbpOuZok{DZF(l zdf7h#JHMmyg|7t8z082=xN`oD-w&tHYm;`C^nS$!AP|$IU-(5G)1?fFL+(9M`*?TF zE%LP%371$Tk}qPBP~=6zHmfzAuON#=@O8XBsnR}P;xLWv^`!I*D&pC^bLil2e?aDsB^C4x03JY?>Ij- zmx4GkZ@~h2h%YaF&t~Tzvwdb3bb+Gl|nW5bed4@ z?JA1lfRTDl-M@Q!{n6sKfT=$=H2sOf^8;fQbYAhEdgbm!=L9!G^AIq*alZZP-%46J z#?{cufpmBL_mR^C5gBolR(^2GD!4Dy@dJpalJ(GZtulBs@pxJ$t(+=K#*fY^FLsHj zC($Y?zeukV-fw_`^Aak8q;vq%ayV5dO+S^)buU%>V z>Px@=kpaGGaphQkSILL>(zqBlj;6+@jDN80sa8}~c&c%D;n>h)d#dF}OwJQLhm^`? zI_Igr#HV(d&VQ59Bi4@?mzF z`f+lZ%4&0>cn_^9B*iXMDW@>)h=fut%*K-Bbtk0f9Seoa5r00q!x^4Dc zUCG~n*N^cWMkrY_x8Dy_#R_y%eVocFI~CR=y39Gvi*TA3jnf=KNm#$lX)dj=iB;eY z$mWipZgHCHQ&q|*_ty3*U~a7CRfrx%ixr`E->sp9W5KUr%?!l3gd#FH}3P) zX;qP;7W_Elg7}p|Ak}&WbkFzzIb0SiVZZ=}ZOC-VEMvM9?nrD5MuO#-_zC74agCv{ zrdpC5X}A0k$WFTz7rP3HhXtN0q&D=S89Y%jD9!FjH;7?p{3EVc?nvy|kv8LytguV< zq5JAX_gWU!hp)MfJf>L_(qmnBLB-P|Ha5|P@I5Sxfh>mr8xDcxYFX~ck>tsh#`myN zVf7(7edBvr@oTfPcsJDqD`Fo=@S+N{1@OT6up(ZsD)||0t;n3zQ(I%?ab(x7m>8M? z_0A#{R$Ni6vq5VeJSOB}U$CUUW+BMnmlw)8y|Bg$$jHqLEbHclpVJFkX~*25I;dOkC@ZNllE~%c<%G)}l@sF3vMxc_;^@>umGp8qTC-K(4 zZi<YyIgnb+Svu)K(V}kYNv0`FZc#h!rWLPSlGAC?cd0hA%xJE#7iR! zA}wM!xv2Bc>(APSaS8j@-1-~DLjJXWj%$UA%5H8RBV0$D&OC;na3(PdF3?0hhE>v? z8BGL(DV3CgBt7FXm-uu`Je)pNJv4J~JqXWriK!bDbC04$MCbZP{szl51b8t`VzcJH zO(AimnakF1n~*pji@5}sRd6iwx*}R+IS7q{G$g@7u;H48$Q^~mC_kWAxmk#1`LkzO=K3rQRca>nea@L~ZpF+8eOYf|XB zHmynF8o{uurFWUB!1@wX@ix{Jj2(pDyYN$ti#9a`q34(oF%b5Jg0U8>o3QRE;}P%9 z!n#GOrQm?ml3Bnqo7d7diD(L$Hih}lJG9l*jHk%9%i{Rd7ki8gQjH>9?hGlt6>3Q7 zka*#%7ijp8zSu#H8U(J7|8W=Wl?DX%evYx5FT4p-gY==R2GRd>Qr!G-`Bw@>eVi%1 z$!7d9?GnM)U3JDkpj!xjH}0^v6>%pf4GDg%JMHLtwmaU(%Hr<1Ze1u{n?+3iezw^c zS;|hP@>aT_{0kJ`KY5FOMP7si;4$om zvIFC5GI$MJESj_~n1m_R*|*f6S&7CBOc)U5YqB8=I0Eqkz-Ydh@%qz009-15plOrr zS7zhFHb45nTp!f_Hlf6MTT~~iEsU%9MM~|6WtkIt;O^*_3|}=SU)=(2L3eV!uGQpb zo-jsyzx+Hny#>XSn?v5RnYJIG6wvzPM3;-FFM**OjdkM)4mGEZXwT60dnqL;lPz~S zZT~@$hjjTIMkL8W<#|4~Pq4O#hf(zE$Pa%tob zt-fe+_DRyl!@H-ghpJUbyGNIMh<)JlK7v6y;ZNRLE#Vy`^JheJ^|{mn?R|t7xFT2k zzVIPOCDyt)kqrg#!O28#Jz&4}ZndSKG1@ijCy=QO;hc|6^CVy@JAW5%S0t;ga+0@h zRXI(?E~$}ep3qBkElBL1?H;x4YLNrgw=h{P8T#|!w@(SFY6JE~+4a0SO)N+v{k8t* z8!WsYN%Kj~pX*)2MM`Dl5!?(FZB3FMpP8C!+i6w?)`gJG6u|3QK1p;!(NiXsW$XRBHfK18{( zDk10U`|*2YN1jKq;xfZPnb!(DTg7ps!3g}dW{uIOPUw)D@)CYf6QHKN9PgiwmHtfX zPv>0|c2&7Wr{!>q)|lO5#N#QatbwMJ#!1))yHJ)8QVI2{T{Rg`Ze*!Wo}6gXZWGl$ zYjSg2&V960O-@v&|6EZaF0w7^AQvEre_a6!`?=5{;Q^YP5f_GzLtW!0AwuLv!f>L! z)SAa*nn(NJ)mPY#fRdaKOG=ak+JV06WN^0>Rd%vkB}XfhqTV~ztIZdIDxGh_he7W_ z6`!`Ci7oFw+WC)}SfSi1!#i2+K3VOG^8k0bc9P_eB1$6KSUp)4C#xGGeOoY9gI2sz z^Xl$u3L+9Ku;7@z2Whn7L-FW52@VJHBzX8j3ITZ|1{#dXB}2hzy4K_%x}C{d7VHmlp(_WtaGukCF3jMV z3)3^=Lg$8D40l4`=%5ycO|V4I5Zl-Z^R1$7(qt{iC7?l z+oG0y!wW^NcQ^>c2}-CVJlYm&5sXwvs|2A)b<9d60N&vQC8Z$n5@MgWA%8*=D?;j2 zqShx`2}-hrPSy~4P?72Q`%;rO#3Jt}NE`CJ#z}?G>57O)<`Argmm?!@em{(3!mE~% z+o^66^vG4fQ^bn~dSnHmgh;3?c-NaQi5x*8;6LLMV3^;Lph^(rd5!cb9(v6pOmcgj zmM_92w+`$r>$BY66s3=IdmwHRdwH#i@AGs~(8T7HN>uY04ODMAS`trNR@dHMys9ga zr=QW4ltnM=iW>~ecUkRoB(I>T5JCg*QJ|l5@09h2_?2_-kbse2Irk2m?&(=se-BaY zX)LEHh+ADYG}7ZF-KtOj%%;Y-;rEe-@qRE#{&k)jUnD>u*zOr%dPEuf%VHh8U8;5@ z@T_LkpY<0YSyK`k5J;9wG!W&au?9pR=I~2>p~`vmV%BLB^pXwn^3aP&Xl%P1`&kVQ8&1nF;K*g5^%LC2|XTM z%_YLpmudfa&RrtdMCy`9KDarby2J}?YwD7p`I2I3mN7(;0ZI)CTc3A?o5Kmh1fen= z;!@m&`C6`TeugCZsR48i~$^zCmOLLc?n>Y2%wPdX4m}ApKkFI=u_2WH*(rFul?~zNAeP+7Uf2M zUL(sJ=XoW2qSLp@OAs#Tt=~3Y0v?A8ID{?v}?nxkRtlCj!cb= zB98bF;Og)BA-6>q1_dn%Zx~&|8;!FGnJA2G!kh2YCo4!SzuEOigrv_N{)iqbq@Dd# zzm=ZDYV;yOTXLhGE0uOyCE-RbBwl76@3WbQK{eWA)II{f<5kbLa26dA~wXeEZ^C2-_Hg-h|d)t}=wyGAY9Q8m^oqf!^P!fg* zY9GsaOoV%#uTn^XvG6vugP3rDls2zSop;R0b(_GNfaKByRF6waSh3>R(k0 zs{s6sA@skV2SnOMBJvs#N$T5SKzEv!i9tc58X`A?`ERL81vnnFpw(3Q^3GM>eTga; zPvd8IuJHa#RJhYTo<)^|$05!)LyAvp2$CJEd8Bw|=Q__{s?Kd#AxkAv%Fb18Zm+Td zH)2|nwLYu9j{exe{o>B!cwzfE=E2=8YbalXi=w(O?_BAH?Ugpb!P1m~^T-c3^y!VE zPz$h8Hb2hm+Ic9l1Z`QX?V)TTz7kbM`DVf+41G(91i$%r<^)U(KVPTPRB#l0uR!gV`+WQcT8kAxTTDYKAXsGwRVy=l+M%Oi`{CgX)JRVi6j)v_@;#YBy`x zOP_;=jbq?*)UbyUhexECC@#3r*05jHIED`R7lFYvVC~$t1H0F(q+gMu%^K>;p8U3s z>{1-XUXZ;5RO{9MLX8f_KV>J33O=oZz6y+tz54f5u%rUvB5(YE`3=jXF{g^<^I{OF zr4R8YcG@(jRz6%Ba`i0CtZdC`ukz$#TS<|@&`OnrO6%}T?dV+(fnSCg+u2ZQ8&gb& z4``<+ZBSca`O^vvb(%fvkyX`>=ClUIV$`nVoxV7-{R`kTu(G;CBgeOY0tCIMd8bzH z-1Z3|Nb#y^3-0Q7bvrYm8ayH0Zm)xrm;rR_5B%JwW^Zw}-NT*EiC2I7CqMGZPyfc# zFLmCNGwyy+-wZC6araTZQI5ZDTgKh*Sjih}l&M4}ttER%$G_d3^-*`REnEraZ3G*C zK%3>6AC~43HhOcpZAv^pUZXu7D$!2j6+~WcZk>Q;+UmVam$y$w7y-ymk5IOPs9#p2 ziaqDrygJ^q>@V+_u0+_0=mk_K*LWx@s_>)g>=L|9;Od?}Tb(f}$u_C|1UHa}LB2kG zliGR!Qp;u+-DSzrg9B6ii3&jh0Y}s2)ZKCJ?*81}wVk?)=ArJ6=DVw{4PY|vuTN`%ildd1YMW373wZ$;(f3 zCQVDNd;q3tZsE8NX{Fw`gQW7yeU8;S24L$#;QX9sA;>cy$7IYQmrV0{?=B9@j9hmF z9(k^Sp6w!mQ9>YDpFBc|I$VmNxN6PeFjgii;A+L<|FI=ShWgh(` z#-mr%#1=eClQ}oE)qgPGQ}?yFch^#7Q}Kl>K_nBY!w7E zJhyi;dH3c|UC5-zoqSvsZb1iO_UbPbMK^q?xDTXrIRd=xLKU%(9Y4CWX%_8ZW}5W} z@=et*OV9+NWlhjW5SH1)S1hN3?YP16b7nvY0k~Fw9wvfeSQV7j%XlzBsb&3p$sid3mbYU-P~2i2$CQiVLB~ zybBa|@ayhk@cR!^%_P=^K}O%rfiTnqo?}>^fp7-mz*XS?$pn8;YaYH9I<5@9tf1Ej zU(d*Efp7T1q#W!pCC4v1C3fIlRfG;Yz4L?w;RfKpn*jcWj?h<=8f0t~HfMxv6NKkQ z5LW&K0qN*kryUDSn7G7f zPrRQDK%Y?}9R&w;PWX=XTWW`a>`UCSPk|~NxelS=c9}f1EY$c|5tp-HB-`SrRVfpG zH>hn3@$z}12fazLFcBSptqhs#Q|Uy7G;w7-Ld?=y!H`292gbs$y87FIJ~XbyOBd>14WF1l`@(S6ma27Ts0K1E(I?4(jCw z)ZASes2#s*P*X()HMds*)XU`1nqZckbonQ(T{~Xn!neb`obC^-c{pRv;;ZI8?Rw!Z z?|RuEXaYmruU#*iOhQPQxU}m9>EONm#8GuuOtAMs@U&`ny_AZsr(`l65Wbyvy$sUs z2u>9Ct`{AQDhO2&e7zBd(iMzuu^EP}ZP1u{nU3qs)_1P$)*PqlW7*~!XPaS!1Z})ity{Ol zR4b`r=555bm<;kobEXdJeQhC$S<()friOjguqSq%$OT{j$i}7=tZ&!Go<-A8vl}H> zDJVTSWw^RwQglhvVN@QNmQm?XsL~ZGH4@HGkr09RaxaZtTQS93Gtw}4LBZj&4I(9ooXWPN>nPo6H#WQ`>EF zr;H&?{L%?{44oF~XFlR*Y`a0_B`b| ze#MoLBuyJl2I79v8d2J6>iE4mj7Gb8T&4hTy}VmiwG4Q43Gu1el*3(XQx0o7zs2q> z8p%x%b>!_I9?+VOC{h)%{R4BgwtskXS0e=@>s~uv)~dbA+lZ(?n0B!-dA>82Jt!zW z6hx&V7>QJ{_bT?@2$N)*QO4 ztvSF%TXWRW*-Ux=kcZ+RHA6E+^lAT)Q&%GR#fA=B&Ox5pZXSJ^tjcgl%`i4fwX^2U zAOgUe?Rq*fI!uow1npI;s?olq&b!!ayPH+G^@}v^YyeUS7+;Z($5rh;iIbzcCN}I0 zT*RK9u6O#B-x|fyl#x*eXQhF*K{_T^*;G@{S6Ou#G-&{$*8q^AG-{{^u2~oMc^{9m zF~tFf7M;jcbX;=OvIMYY$e{!-~9-ZPi{0TI~^%zcj8}4P#2ULtt1RZB29u<$GLuY!Ys@0G%=_d|AmEj;* z7Jvo133@N#!=4e&^&{|DNjz}fNE!{6&P$MiD8bQC+*=>`i+skbEJ<~UM(C3k8y6#l zm~JYfXR}gOB?#p$1511quAKq%gq`63=@qN&yARC(GXW5>tctA!Kus}yF|zP=0=1N8 zm6e=)7%BFg1_4E~%mWR+WnI%%Z78dpU{1qE3LCM`$zX*ugoP8G=IUKn+RcXj0~wv` z_`l};$a%X<(fAe26syCLNe@!x(MI|ArLS zb43RVr^(Cw4N^dKm*B>56DU2&sx(2BVkTx*5y`>o(Y>_*v!)~AZp3`ri?yBBBPX+DHFFzsZ1{uwf6BIJ1>=>5^&8t*^U_6FKpsG^VhNCKe<6Xk>PJ$xgajFWmcY~%0Vt6OIld+Jv zKV_d^WT#>CYizi(UFzQsid}(k$`IHf+<3Yq+SzedXis3E;mByHwJC3_ra;I*zCq=Q zR-Zw|QtlFG1d@x9ef*M!Tj;ne&~Z2DSk@Ohr|4P_&d6_MGT^owHD{RJ+E1w-EJ~zf*o|u_f=QF>VJKHi`RLY1&f& zSw3~W^p3rpJX>)N%Gz*FSPc!H^iFgpdswKDwN)=vCpz$%?aCsf*fgp|IZ$dI-I2ha zaZJY)fF*wbR#f|h9?r71SG}>DbDTP(mC6?x7@7rksXAG?zTshNqWLm46u%|)H(&z~ zkd=ECkb;fzEp(XSoTfOYaHFd}?>SMv2N{6fIGz?oq%@F0_+=&(XOoMRIh{Njay1L; zz4zSc91z&?L^;%wV$NsaREzg0?ZuuG{rC7)LA$*jFKv;WZP?Q%?6W)9wZs5rz~e7W z(;CCCs5Wr+rPfkH_NId=VS66KiE^?>Qs2^A_e76d2#;n|35yru2Qct`fjXqJJx7Aq@2KGon=g*9an;zaJI{%sW zy2EPX6*j%zgkE%oJ(80#q##_^dm5^)Y#QsQCO4R>_XWABqz0`6rgU8Gt@eNbk5POh zaGM_F2fM;_d(-&4ox8EGjL1_RCPA>4JI1I#<#?WtcPDQZG+ywbl#`pOQLAElE15-6 z%fV&-?Kgrc;7YtND(JZaedvTH1r@yo@&k3-@jddN9M*e>BrspYKP6RP-}!yzMA7?S zqIx-8W2g2>q2l+xRQ0a$j}+~Qi#xtgrV_vZWvZ90b8|0FcC*^2OjqO}Nl>O~k|RSY zIo4?xSd)sE>VN*PpE)RgutXY5Qe<@Q;9mWl+)@qKNTbW!#p?KzV8kqs_zG8`^PzyxuIKg1R37g`I#3kC zJE#um!CG|yZtPe5p*P7>)2>rf-bs9Ch4meaJowNGc*k$nQ2ZXSBbM#m&R{ugzJV4= zexWPkO{+??sU7EFHm7@|OYGJ*@L^nt)CdJ8HeLfY96>`T+766ENs5VB*Tk*xj~uGv zA#)SLE)m9L6cx|$%pKOuVc^;EMVO0U{BqU2%s<7Ii?A)gA-`Cq7SO9jv{?dxwlDqA zpGYZa!iMMvxqRu-l86g!UcQgZmmDqL#|4e| zZZ3z8mUnSMZTosIZ#i1Ln+rasJGijRnFUI^;)!9|$DzCn1B$2^DMK1ag5OIN_Gac->YawQ}La#7LOYxBPjf zwfX*5NE<~j@l9Z1DQsuY@2nssEcf*f)V<)n6RIr_Oe%GLebTkmImbaNbquLXf{aVevKGU3`HmdA&<_&-{@;6`jOuVL5x~>!pvsQAYB6n{5A<(hj#tO|%_Jlv1WRg;ha5r|)p%*@ zw)GH;eLTEX6ZBAih8)4W?m=G0Otx^`LxeTerFQIl#LzmZ=hx90C0Foes+4+^)^8gD-0@D8w&JFE=$Rs||hNuw;Yia13ky zFE}oM7!FSYkI{d5~;_ypqF$!=rS-T>4Gdr=9UP=Q@B8grIr%R#iiMGl*lDEmv*@ zhOt9Me=%2dQo(MiQ^VA${kc=_uE~(7I(iT7)3KA}c1gCT5u%As7IUjWN;v@;9(L+@ z(biq}rJpK4kSlM*4YIaK>s| zPv1TDx!?{VW^7ZAB{G{8xzlfBb_$T0A(4(53P?Z=TpMH{8_E(v@c1QVLAnaD*}`mg zsl{fQns@897~);Iqccw1>gfCO(;262J-t6aopIXe7EL^qpUpUJJVRoi58P#0K$dje zlZVbki*5Kk^Mxa>G`5b$*74Yq^;6$@^sBL`_$?buhSX{tW+h_*vHk138N~IY`3TUl zurE$09V-WBoDn*fs-169!<%zN$HL1vgmmmooB0sZu?{rK4-lN2(@Dn?3gdLrvBcrNa_N+aK~*}1(yB^jr~Nzd!{Bj2e~6q0eO@*(av zT=)QYAN1XQ+`aMvz4$)v;4X-^OTp1@px}sXe`EXGrNDBW+vFzr+~y#>02n*9=fmFd zb!-Lv(%Fk#4n#`Ok<>ca6$&gDG-h3J+|4tG*ZUXDr$1dy?C0hutDD7sK$^^fU_dM4 zK&zqgki~R0SO7yx7=)6UFo^M`Bh&B*tp@8QlOBj9KycYl?o2L2Ai$*pK?n6Scrc2Y zJTj=yyI?&FD1-W(3mOaRpg!w@Y&fKj$6V0JM1%T_3#`zJeY35YA);F9Q0>#?k!r~{ z110OBppk9J3u)Qrvj`!Tq@> zU!dM|bWgI!z^9`uns{1l_3a|$OTx63h-<1=vH-tm-tJTqA;LD z_s{k(S40sGFXPj0j!8E5Gc*kbgzLhH!?Y#qMm1qON^{}b^FK|^hHKC z`f>wwC)kr~Z6I1f4FefzUeG?7-M1Id>x#+YIbCttZu-h}(r_TpLn0_&9WhrD#U z2Tr#aFUI|89scz3xCe?PP~*OS5ezhd#@_-OfgF$FqX-Ampnlmie!+aIfy#@-=3X$l z%`Y&?8T<)JKm;Q)fUGxN$uqMO8Mz*3iY|aM!isa;3w_p$7kfh9_2NR$>ZVQmsN?L& zowKl=6W@;9_5GX#GHjywH^LwYY+(R_AR`V4Mj^Tmq+^LP!r~OJ`xPc*#O!hQ1`|e0 z-3r4m@Q*<}2dXEBk=B$Jn6$X*%|}a+_!@38$vPgbO+O?#RJZ8$LL|Z;78T!g0Dg5Z z%{ORZF@i%HI0?jJ#6Y$8MQa`E{nkU^Bm}5Tb71hZ&IqJU!-(*Qy0qv6f(L@*CFp`=2EqN9^8az-1MaUjP=uAml^;9+4!5ZvYzQrOZ#x_WZ-!ZTdReg1#i?2Nx#rBF45!`~^^ z{tQ3P0Ryd4sFYK?&C#i|f+>|gLl;!(c@ae_GkDGq+Lf~208*;-1>?mt1JSj}G{kwq zrq--=%G^jTq!uXS*DI=^Y5n{_Q}`U+6@brhE~tq&_nZ+boHr9B%_BYML-Jn=Imn(U zTd#aI=kX8l(Ry**c5hkqso@=pb8+(gu%Pf}lWI{l z>m|90^_0Om95kV%&3Dcq))X+jLc4LJfPRg?N1+Z#@P|5}Es74w{zGh%6vq0o;vSMv zPr}&#SheyVLl`Xf^hC5coKx{HBYe$B;5ZQkxhc5f;JHRN=%@YtFEk}uK1d5wU~qxH*eRi&>Hzl`Rv)n!p5QVZ1-JN44juVL37Wnu zPQJb~m>XVyn6UeEzC1Pl?=;q@B|URJZ&?#cp+J6O@tm7t7da3q(XT>A=xTkeL@ zS13e{8DyHDHX8y_jARLULRt`c2X+a0j8MzMfI%I&7&J3b1=NB*>g2ybkY%j}BZzaI z7(obCleIH+4QdfCd?VKuh@|`oMxp%tVM~ey$-#g@{c1>NFk^8)(A=f3xKxbW5{{cQ z6F4g@E?$Bvi71GxriB4J4=HCLZ`D?{0g|E7n9E4C&AlDHRge?X8EvRAAt|zg5X=Qe zQpAL&08nI>6$!aB_vZkE8AQ-dj2EzK^f0s)t7BRsn*I?E-mFwh#k5&Qx-#5?xwfKh zdp53qYt#MErp4hu19axJT2X}sS}lv+gaHcN_yAZ;QYU8=kHzGImd=gP#TzZ1n~9*H zrE?3~5+@T#vd%4C%W88-hDd|svv6l?%SFBST{QJST zi0Qr=H<3rY@@#==VW92yQto$D>Yz58k`0i@2_?A?fy=V1CDqX0B)&9I6pu>#e_-#x z3}*s$-ZiW0)b-^#G4MspvoiqU|g+O^2WSWt&IO$ z6^$f&6J&upKmvg327%3z^AS-FdAKXZ2)Vf4e=p8<=){m$Oec`Ekie&aPcHGT!vhSc zK#a%povg%EsKdZho%kvuP*F0M#TwX7J><4g@=o`Nl5x%ttG{5?qci0{>Go%Pv!w&U z{SfAW4c3mx&|};;n!FD$K$DkwScf89LX&TWsjyr=;jf@Iwv!Bm-={<9fNn#3)!Ig1 z(uPHP`otSEI_G|e1m;(*7irx=xj&>UaU86}WOzagoEe^~y(ib!oiu#3PUHB`3Q(Rd zJzrSejiz3l*|^jd8MYo%y`br%?RMzx4(*JHZwi~9b(b_p>Mg1dS@4r)FvVaSd<8vw zx{`j#fFQF@V?dCmtEDR9p_S_yA^t>$1?A?qD1%C21B0~QtO27$s2lzZ6XYK4YW!Xe z7-VSlUqA~w8mwupS+b$zanPX%iAsGJI=B(w6sjBD4nw6_CPq_hzb{i7YgMJ^=n(l@ z8tL&derL79M$+kS-h!M?n^Lv43Dkiu+OE!(44EUe-KEfW<LP}0Ek&K zuO6n>EKEv}@nmWIobUn_M>JER##f+74vQf*~FFQZ_e(E=&;% z)yNQkoQShD&0a)h3FOE&d1mTYQkEZNYk#*%$n?_3Zdk&6PH*^&+YYD}~+4<3T0 z;CE&qrn4J;>0Xz`?UE(?T(jm4)*bnuvmYf(wq%w|@V{0R6;mIU>`>8U$qrL^^%^YM zike6(zQ&McS_~BCY-F%dGf=>!aPF(3O`P{e^3W#Qstbd99zpO+gxJqn^CNIL7@!Dr zo)q|bi}?*-EAx}qz*1>f_#6axgAiPEZ`%2MVu73toHzT~yfy@F5m^P4r=`g*l zjoW*DK;CNt(j>N;X3go_NOFtxZLf;wtQuc^ecO8HLXBH-b?@o@6*`Ki=;tBhSU=To zRLOpI^D0Kakfy`pEfU|;UZNF^%#3pnW|X9hCzk2sb7mwRmf2{Oi4Te%U>|40&+Y%;q7usOAox+K7=HBlghG)0wj zF8$wztjP9Dpb6(s%UB`z<#7!ha}T_#oLTY#6T1c8kfuLj=C9+0CBhZf*ocC$O9U@RqCO~ca zW#&83`m>5t#Z4<0^fiQcP*fIr3fj(AtcOK2(y_PBu8Zw)L zA(#DrEZ0n!;t>Or-@#@eQ{7P2P}|0jCLwaN0_2YayF)V{Z?*!}*zYv=$euH#DC?zD z^|K$_?5w9`UG*>W<8Y^Qw4>cn%`TWfgSFt`sT1C_TgY&Qb>+kdvCN#up(fKziD{;( zwmuRc%I4D)YK0B~4;Lbb5E;vwAeT|I3>l($@Xijw~VniXW+4S`8SZ z?pP~l)v=4v!y)`pULLl!D13MS>;<_$0^vj(*ma~PNs*zi(C@#p+I!+(UHJa*`@s+W z)4%h38m~{CL`Ilv1#fa{<)~UAkE~i@(aP}5N|n20y}5%y00@-@1P7%X=Sta`KTZ^~48w?E+dKuAA6vuE@C~NVJ%cWJ|ae*n=hO@#_#5;Qw|Ckz7F@7ai#|^?9r~ct7HIOmJwd3W1_$6Sj_M|kY2VAOsHogi__s(SK;Mo+grU$ z^+%Joy;%z0C)eJh%0FuL=`G@0NOAnd70gp%lx-~h#Q~iMZ+&fl{-vQ2vK5vs&}9cz zP0c(4$(}TWQO@HW|AwhP5CEWAqn5QEArFLXe88Rn3L1ke1}}A@+!PT)6@!(L)FLzF z!eFx*DH+F6z<9A`Q&iWbLA|JCO4}JSG*Zi0M>Bi=;rY|OEtZTxFumrFhbgbLnDF(C zbjF0&M9?nDg#Xm%#Dr;M0TaF+oD7|Dw;2hHlx`jr2XgXXeu&4&hl3!J7>oj9;3<1K z9?`snX}l;e!3u4%IL}L9xG%sy5(S4bUp_DSE{NdS&of?f%@+_a!OZ)G#7kB#%}bua zpCDdxURUuJUBQx#O@5r!4|s_kc33+zFVV{iaGLQF^voGAL7`6cGVzi#O#w9Mv3~H9 zv;E*D=la1*&i8|t5I1FB@=+vaSOZ@uBI33468kmi=8GW%a`$XtsH5It29XG4hKH0A&L)(9&BPLd* z;n8G_Wc6_I_M_zyvpYu0ysz>SkL|a<&36hKci=R-VA^V+pm8bHsNKr9k~D2pZ=KgI z-Rv{)$~k8>J`M`jvu-hPpqC`J2EKTac%$X47QdZyRwM9GuuXLierrv>#hf=>u#Gvl z0>o`%R*Y?8*0LPfhG3T61c=*mnppN@ExgI7V3vJ`aGXVk=iu(G0C8;o^3&~%V&KtE zD25EY1B%)3Ob2cb!}HCOoWhwU2iB+5T67(Me>3-9>5j~`Uf|&H5L@=aP8A%!U1mAA z69CS-4VFmurO6@@(TNTu5ji@dKgX(@tDDH&!>z-r$R6a?`M8LQtZ_knN{EaE+48K2 zPZ(nr0GiOn2{RowW#3V9vfu!>oa$f>uhqHGmeE1MZixUCU-$* zsM!WFlIA(VHPJWpg_tm z0EQ+`SR$-c5N2gjobauJSn@}sg3S3q>;-yGFs0JVh!Y0oFyIg;tV+S<=^EFF6gC;F zKMqA8*8^x(zrZc(ziwq()pKctB;c3;l|mDLVuR!z7LHM1LI1^hUglsFKDSoPuu} zekM-lsFO5%4z^LqYV#X2goAa$Yi>+&uul5jI1>uR;DC8=Mh*i#R5A0z6gj-4$l+Z% za@bK>haxKLpkf+;aGHAZ#?2y!{bc9J;U!I-j8|!@Shr2|@{;YGLR#lNbf_b&F-H!g zN;-0wYuX%|&0aZj*!sRt5&=tLZfN(j$l(YFn2#LB-XTgB<`%^ufQu=*z)UVj4yWh> zv%nNN{7mDE&5^^KO^Fv3vIivo!k^s8;c7)Pm}KB~oa#A40g#&ZM4T#SH>P_&O7*cQ zo5iS}5xf+mx|Yme;w+aJr;5a430qb&?I?e}ODh4~Imnso znWp5m#W05fjz%D$)>xwAntdMNzRK5&mqTg8ihT=lC_vy4$U6&U2E2SdAIOZ_N!jHF zGTW4Q@jzzw1?E6z$$ICJfxfY7fMdTm;>o+#ZW!GtYaiLs=stqyYTBQ#J+K7!cC8j1 zzn60M>dP&K5X;=png33^V4H@q!Ah@Li^vKMyPzj7Xo!sc$-L3he?Uoz7nuyff?R+~ z6D-29U%WwssX+0Kh(fj_OWclNUHL)IT0gh1WN+-*(({!{EK5JVYmLfAaBU4DHkk99w*W=O> zsz*t}){;<(ZLZOCr~8^xNvH`< zQ(34pU6+JfelDOuXQIIn=_dj;cVl~^k$tLKY-T` z>`xNvOfEe@sBd5x=IeB~uiBgL_BT>%*g>%Tpn$I_B_Loi3S!YgrK>M^ago=Ld`J?! z&pC2+mP5-t=_RK0EO$1%O7J{>F9`(Fl6z4rpk3#BaeylTX{wNm4WtUJlkf@2oJ^+H z0Q!5f^oYVV`?N2&Bii7yg*tA!$$9D+OY(B5qx*Dm>ga@b!I=aKXoB~7M5K&~J46VS zNW}eV{|MrKzOm75^8kGaf}?;*2qfRe>mSPQA=05Wg)eqpF{|%gYX?Txs|#pb{B65; z00AX!_l^v2-fExcN3$Upk9W;88}mkyzfp{?nFWT(pydoFHfV(z3mV@TuMS19-9uh!7i^Q|~DQJ;+NCyQi5-)jT&cp=?pkNz`e@t7fBUm!5 zRw6(_(&w#KGs4~^H9#E;@G%cozY_QqEPkpc>C%uGp^v-1vg%W*Pc*MZrD zhuD-00AzGw2dbTY#1COKMUj2rHF@)5WEHYGL;kaaw61cfp|zQ4OeSI z?G&Nja5e4a&Rh+FWvYEW;%d9JSREdYj5pm+skmCR$6IJM3)d6fkEx1?^|U{m0D}el zv%NtnYPf^}a6Bk2*F(OtbzIV*$hXt%j(^qC+g33`#?CvH56|qy?Z7`1 zBABMA2Wo+`=`>L_FC=X$Oum7@sbBHj(&B193(-85ztT2uB>WX6}qYYU0)>uh8 z(u7M^*F|iLw1{iQ|G?c<=sxd6Bu5U@U{RN|I6%hcO;11_n3yrH7c6Pdm1TtQOY)Lq zIX=_zp#lw`ZUO^$MKA|G=;j%Vlf)Q5`mr1f$nVFSAML=vKShM&ffN{6DliQ_>BM($ zY;5Q}BDhN!4I9w_6TSmb=OY7CDo8|9wpxuR#OO_EKYE2(>gANWv{){GfpIkdq?cNd`C_d)o;jIwF^ggYKUxQ3T1qUkS z4Vz+F$|(aSt7+CS2^S+kHMh2=*49qE`rAMGkxzd5H=cgUp@=2aw($%&ruF#IQgN(^ zTK55Afcrjv9VfX5mzT&P_vo{m&WwVYcKmC_+MlMFeW}-TnWfxtxa#}xdpF(5P-X~U z!5rf``6;G31@IL0-{!}9jtte9@aI6|L>}BJTocD3`nSyoJF>s|2&Du_dgGA;B-7oY zQ%Z;}<$OzkBnB)6NFo<1K+@u2PuY7G2DS8rRd-Mc%f1PpRHbhxQ~`bzvJw7%MsL+8 znj{@!bwlcYPl~%?jF^Y}BP3J4%{hx?m=Xe2_~d@IQ?`YO&7VSWwh8 zg=MnEHN}{YILa-{W>V%uHj|VV5}9IBj;Je2T9}C0jogK*Pxxk|>faiP3@dX^1((c8 zX$me`pz535N)26sIW@tY>Rp6#hRh&4L5?TV8nfE0P|gbyrto@tpEXJ9EP+{zO?#uw z!^xvB6-Xk|nooI1MlS`XjK7yH0a7Cnk2H125I0pf-#IOj8Tck-r0LBTG$>Pi0aB7= zq)IZz&0mkI#^pWJ-i_0~<%|oG0&hXo;3tB{i#_V+r!w&OZd4P^9%(wPNENEQpdE)F zjeG14v6osMmO^cx>RN~)Bf|78fLs&Ns@KD_EPzN;z0g&Xoe)5{Ndk!X`d?pNa~W}> zZ>{D95U65o*2sF9Y$pV#DdXzgW{up&0s(}MGy(`?IMXDGg6Lp-)R*>=%UH^G=CGb; znL&fRKc|j&1_;HIKS0vw>hzOirt1G^@BM=G>(Qc)(a@0nUOOMV~7ATG)6`O>>wu2 zV5S7L!4M?~B0vf9j3%QHK}=EdBxd*LvjDXe24?H#Xgn-lI$VI&X^kJq;%!_FVVDMqJ(9H2oR zc@uJsG+YqG)}iTdIt0|Wu-_#E5_0!UBC)JX#Ac(KyW;0eqEV#?2T7Dp#)iuADs)_c z`$DNw(iUU6S#q$H@UiL`$t*G6wq7jJt3AB!t2V6u(xzSPliPwWuo)}L15o(7p#88q z-*B3!#Tb@B0z4>l1K~#{Hk1?K>Z(?IsUtSen$JFTv1qPo9)B3l{_ki>KmiI6J^vFEAlr%h{Y>YO?4*^Y*^f9;WHiI zLJp3m@R!M${;q%y$IH_g(z`CvBnkeh)feU-xeeq{Tj8EUQRa9--;Mz(dTzkXa$=nl3x;=p%*M22fYw{p*Kzm zY7r^eYDmW_nUF!}R-oqL?>}=(1Uc z5pO?E*75|iXbzpbvS`ks75Q2363y{<{l~2|4uBqMf4rn<{y{`@!o>fX6U`5_A}PX= z73e<~&C}e!Ows(vYbu(<+rQYN`H@5^|9>Z%Z@hM*`JX{=_T6UMJ-pf3UAJV7@W~t} zDL35Gk#b{$e}()yYIYX#OrnYJX-uJ_I(~hKM#ua(`S=>SJ$!71=8!hXT<_EtM zhPto0pdg}VsPF;^v)rFE;cw16p|e+YuM?K;2$rm|ipjL{Jo0Z=@XT5y5Ie*z8lMuR z@$n{cxcLlBW<~UdU+pD&+d%rKwaccMlp#q)|6t1WPdrURw|9)-Y{-xy-Rg)m9)p`l zi&pZ((!`F2${~Go&&Qh{Vkf;RW^dZAzRA(ptFkiNwu*}(QnDG-&PF7n#}s7*$;&d< zls9-kaliB#DO|^|Io&ARhqu-?72o!2>N7`~$TLD1Kf#k*Tou=0++29< zBA5Hp--}4H;o^t|qINpNav9x?Qwoe%wu&d}?re42;q&q3rlXR);zx0aSbba+Lyy!jxVo)k0jyKJ* zDDy~pcKZU{m>84#@-RR7wUdk&RQxwc-T4i*{BGVzxPT9UD&jJ-o-7gf^V}vsmy!AV zz3I8blN2O7Su1)r4@F1$fgGnh$a)gmdb$B;`fp|ZKy*cv^<~adB1ma3bM7@vhVQKb zP^a(|k~y2#>!$yRaL+(3j*dza-tK)P0(>tqaB{M;G`G@BVgnaxN^3xgoRX#`)&~+B zg>|Z8M9DY<>$s-w^hkoUo!TAG)b4EZC>2r^SoVxTBg`Hl^wO~zhH)N8bU%S!ri%?G zm!sE0lyxNIN_TtpjSAqAo@3$G76^^{!i`}1xW!0$OfjMJSjS+_V?=~Q9tu&8`>N|)G#+lhE^f?^3y|hgDeKV_vT~8byAQ9DRQVo`_2%0%onC6 zplXy4YCf3*&40R#PJ#4v8J#gz^Dl8)^DhzF^RGw*#)0WSFIRJD|5_p?{MZ1?23xS+y2Go9pk?>F)1Rjcm06cYyo?pZ#*TVaTnjCv_iQJ`@LX!96Hdf;BcgAU_HR!z0{|~ZF}3F%yBzT2>gOxM!t;fn5BQ6T z$_2j2sogG#&8E;`!sLF*LvodgbI!Zr9{3bJ97o@z2DZK23m*epXZ?@O)<3pA`>uPS zY(n;n)?PS}wDiyvG`O>whXT@M@@7&7{d%U=#4&GDfe4%CZ`cyB_1V6RW`F^zs>^3s zh%85$DZSbL9_TLQ3wWRiA=es02|casW`3#~O%Fm$?1 z!B7ml6b!|>OTm0({rwaT3U(K7GWv z(EBD4vK(*&h4Xkl!;sMnBLv>n6|@law`$u=!5mp0_;aHcMbd7eBcz;i3hFEEsh(qt zx!;8ZB2?-IEFkn;^fq2oX7Xw9TE-f@c*cBKosNI%EV!O+3PAtN=Gb-976DFKuY&T%)Nk3}?3 zFTZIVaj}z@P%S$vdp6@`KT&?6k3DeGALXEIgTxMfu>1i&+W;Ui@eXY6Vzsf}6Md(9 z4y7yVFH8}o2f0TC%r>RxU`m?e*kINSyQ&);FM$$7NKgq}P`24VoRM7s5bx5=iz+hI z3k)?#G*pFo*AxZoi8+to#sSZE{Pyg7uH(1o-rM8+mes*zj)6Uhrk&`Vr!?WBS(+he zpeqL>uXIIGPROJVLL*W~S5L*Q4jMJpv~bs_x9d}>x6^tG&y(Du0 zfm%-xECi%7+moCIZT@pPEn(FzIZZ)mkie3h)(2|qTBqXvyW}(pVwcEiq=neNE+!Vc z536!o$X}wOrp#SA4ZLIN39nfyfj@i7Y3?7gLy)>kf?a)>Q^#`R}wdnYk&}pELK~b zVsJ2?o=C@z#44yExgcL%aY|kIB8yX*c)W%(62lWAGzCeNgZ=U)tz{Nl8q9o}8Vh6> zwc5F|8muF((mQ310@|u|Cq)KWi86!Bpw5`eWz?$SX*LP=2#qB4 zLvst)1a0)MGtT+J>TX$^r^3e8fq`JM?APQNLKuddKl)cc_fv!G3rY)Lku9}_-PaC1 z`U7i-9r`}pwt4bFtPWgVfbkBg1IY>FZ^Hs>57MpoW!#s8`bL z^iLC4=xVqsj1k_>lF70{!_?eJf`S|H*=33b#1d{`xE%7ag)j~Q z5-@5qUxqDdvS*K^Ijc>lc-YkfzZZ>lG&`i>5&1>K8EyYPED%pv4rI$O#Af_}e!rbR z+J0vFW2Bf0;m|SCz7Q@GqWSW|h&LQVvM-Q6AfNkC>_`?KoI8|;!VeSI8y+EfccPf> z-~LXzLQM1?!Gz>I!kiuy^~Y1C0RA>E=~Zf-WK+do&mYaq+K*t0gIEm|yXvvu3yxS6Bs__e4oBowLO5#sJ5PX{SejN zD-S!WyGKuc@5p4w<}!cr{F3|0nxIM=l(aHFt%*0A2)79^=7DK#&H;b+hFF^eanJ_Y zoB-)%_g)JoAK*8A#{kP9EKuM9(fak`QrM5g6uzC_=P)M?M@=+IDe&~Ok}6(F+z;%h z6hE`E5Jo@e_`nv&JI%6X1(;B1fnCpA$ytdIT^7s-j#!TZHr@2 zy77m#e9$p3=a0i()VoGL(8xnb>24y+k;YB7Bb6u3$}Wa*Oq<9^Flm6uA$;TBPp4lwqNfw=HNmZI(-i!$>jYr>3+A-EN0?6Z^G|0K(Yz*a_-{{o(Vgj%x(s zskAB08=yyV1XxZyuXox?AfT%v5D*7#I&Nd)4qqg{u`d!?^O#K547$&jqO+uhF+;t z-Y!2sSfW`=<{9_B!rMTvbT&_NHSqP}JPDbdGb@RcekRBmWG-=16cepQCzz8aLgxf? zQm8_k!<-bNkP^ONP`uLfhO!AsGGdU=CNnuC+?K+nY@~yy)4z^Fd}c$jO_@C1apbe~ zNa%{$|G*i>gqB)<>mA-tNyZPs zL><2_4d9el*VdVhQC#h z&!45`e`W)F3mtkH3zWdU=N7|_Vq&c82iBPvesP8+t1~nFa;RGOz9DVqFX8TEWduLc zkP>NR^CYNVr42G(g*vRSO83e0GrL2wlbh=48M&(IUnh@D>GIWQ?6t=(=gW|lUoZ8{ zlPiIrwPziNmkYt+c)KKO#h=FNilc~vp5(YRKrILV2&g9i>8&$_*z2sWgB~eSmGNyS zW8Ar13pTkdrrb~$Dzp+H(ZPb(saUXZ?$;_JgkN=<>)vr<##Zp{i#I-mS16agvxhmp zg-Rzk-LZj2xYxf~b;)(`?6AsF;f>qnyQzjtkw3rhJLB<e^QBnmaA9<*wnk8~t#-XEyBaAlR>CAx)PA$jU;m6f98`CG|mz zI1LElG(d1Dx8wc$ZadzGh;9cJoxn=~QzX6J7(s1ERY8v?js*-6Xw@o?J307B6d>S; z%+nKXQnt0+@5JcIgNcbvQq+(x+uzi_BO4!87qGP^Z~8q(A@P9fGz>`x z2?ZkKEcG&bzDY#A&8_Z~i;j=qM2qX!Mj*`5=GsVnB(%YTl4Wa35dc3+Wb~Ovxb82aU z1?wX=?h33pv2j;uOUp5Z3J{!~BITRSWzYdtDJ7^*RdA|pToyV#BhOSdOyxYIB<}%E zRn=6kHA-@wQ`I>I-<0CI)wB9WdZq>h1J_n)=&q#Dh*N(U=(0Z}vSa_ls55PLY8lqb z=8=l$JO3Oo3uELCvsFNnM8ZWF|586|REb_3Z2RD$oE7{z_0PdcTW5B>vC>kvOU5<0z; zC)0HsMa7xueByhn#8+Q$TYOm_-i>O5zO`dHr35Np6gf%Vx=r5Tl)MYyA0F?=1BTR{ za(+rb?=9yuJ?|^$bETgz=Wo{UtvTl@9G09P+{di6L({7=hz;M5YYGgPuyn0AA9af0 zl2SBoF1cb*U^#{Yz+IS-99c=y>q&?U? zRG+1JZB-nEu#s}SdYG*={Ui`h6!+KJ!E1|;)Nd>PkPgjCcW6`9V0@-;=py-*ZOHtJ z;Fw>r*5p@MX?{hB&#$n&{0g7TuSlEu6+V<-4T)$N)?m=?pZ+jl)yB4iCq56@M}U2# zi9}>Ev=mwDkt#!Gbh7w(g?y8Kh`J=5o9?8V>rsx+*1{dj#_-JE$cXhZks{k<06ZfoCj>YG(bD1!rNwHNC9~ z(}ZDxY1;k*(+-K__jRiB5GY55({qbb#FpB)mYdEms_FyXZp}(@uwEcsd9skOzFAc@ zFsx?fwMAdRs056XTTBu>lnqIJzN5ZCy9F-Q!{-@tUdR1?n@ZS$$dqI$VP= z06Mx7NdOXDq#8^Yb--hAvJe?e-$AnWqZQm{^Xx)jU!UQEQSsX1s<)LmM60BCE)L1f zSH62g89%Nq*9Fiu12jR?w`SYx%^@iOo@^n2rxG-MhX!Hiwh3Cg#4d*9eYXPG`bMW8 zNS%Xpi2kG-r>m{7qX6CkET5@%<*tjGg}0igwQUTj_Nn;->!LSn;W|_b`#|Rd!1n;~ z^+n1${uWNdr_Wu2-(9TC@3Y>?;&k9VZw*BCouIrY(Z03&r$1CH&)enbhrp&y_8S*9 zE2j~8;L9mWOA+8MoZIE9>NzI;&5Lp|ZcYeR!D?ZYH9omV1@wFr|> zR;x-?cZ_PdZU+zQb!g>2Ue|bK9rF#|0m3$)FK@?t;&YIHb^*-|TpdKTCnq{8eY3iG zmuT5LH+t0vRQCM~#SzRIz_eu!d>gEWSGzE+#hE)u{-B(kJ;+xUhY=2V6vgc2{CF&?H0i^FT%CS0{OmNtR6Tl2f?0U4zG+b`m<^Gu%ao z`8D*UZLfsNF)#)x zyVvyPp7=tFM&(vde0AI8HPIf#?p78-b8yZ|$XzS`Hclm}Yh#gH^`w5!4aHyK4T=0# zp(76CcWgi=HbsSKzKhu>5|W1C9J+lzu@`bku1N=M9irG1msm%}f)IK3ol%dzeQ^z^ zQfAjY)ZG2f+c6m>Z*M!aA1z?1M0cE$XCS8~-j6Yj2P9*cdd!%95)U!h152@IcAyn@ zcv}k!9fW^PL(?5nKx~T#v!tt}0D`WP@_5bCG$8n(@OM`3)lnQz(u4+cB{QJEOy)8& zGePd`HDrb`9e^??K)UJ7r^#ja5iw^SphYOlFo5Lr!_tM*RG+UvR*ZuThnOI%;T*`3 zj!pxNkvENMG@G__L|y?APZR->hk)n`PTEmVf}?~)t!H4)ThP|TI;R1_X+V$=af0A9 zAn3L%3Pf{shn<50R;uGlDssh+`N^I|w94I~=@^+1I@&sx|2qV}rb_?6U4|*tW zFJ=I5mp;d950DKHFi3v<10m`E-J2( z&#q&w(hCKaSZ7_4G3u1iA*Y%24)4C_x%aZ9=?3o={h1Fc3E9K&Wb%*tdsq%#R-0} zOON9@_9^}xJ3IXbWjl?_zLaMK4D!AsJnWU@SaobMoFdWWOp+QZxlvV}8!&0%I5%Kc z*U5}qNunH1zfMI?sor;D(A~2=?=`4waYnR>H`ghM5`BSw$PHml+K|ukxQ+otz3q%N zIY92V<*6a*ztgQXdnAYtnxGXH+8YJ=kyz)3-;x`Cd(5QUy>4Q)1LuZAHx%+(P`$^B zH;L)3&4zC+Xv=1Ti(p}}tmLIuYV`%Hkh~Cq7Oa@B5RT7;Cmy5cO~NzQzM<24C7-$vzLp%O&^Z*j$?DB@Npw)|PURr-ol&rMo+ z8D_zkHHzs0p+=gpV=U|tbTkdt(kBT z`GgF(jNarM#=cLCeIx@L;$VmB;_*lpQREA<#7ONhS!Zj(F_=d(USb3YtWExsUt}PO^}! zko&kmsGyf-98TX12`X82;2dqO=7+gf1lV9HI`&xce-CoE({m6wV2FwKQr03?(ET^7 zPZl?t2{~65@c3W>sTnp0A;z3%!~4^#gqJ!HR=fk%Yuuo2~>O+-^$AYwnEDB zh2mKoYTMQP8uiutZ_J|B39y6>Q67D_7W>UL%~DNhn=S(oscnwO0?1WzQi|o3Dx)B_ z$R|0Z1nU7yqz4b9N#}qk!Q1qTjLAw7ipke)ZMsmM&((80fC=<(n(BJ~$<%~%MvY|7^O+jaoafW^d>}|@9JwED zZDNw{z-nzyrrWN~wNe{OlxwS8Tidr6FFfV_V($rg#Wtm%+G zUuiZ*yJjIAzCoK>hx?oVD55_^eU{pu>RE**n7eCk49)T7ps9HowDs@oQ2z);d}CuD z7&Mgg(NX!OjQ0nj45Qd?V7&!D|00E5l6Sn2{O*d%Ybc6Qs5MQ=m zLO+Xls*mo5_4??B_4?=rlc2%78?&`DsK~Jm-#bH)^w}_cr$Rfbn|n2Z8VKkXEXrWJ zzY>euk)fX@ZWh%K78Pg|LV|d3l`u#(v28^uH6Hwpz?eAC3;M8)kEdC9L{EDDDLv`- zMLp^Bqk3MmU3h^UR$uOSio3ybhB;T6m$OLtiS*#@&U$;@x5I0`ci`nWGotg1ONI4m1wUS9R&McGM zDheAi$v0dJMJ9oBTq={CZ)K9OD6MWTW%AyAiiF+F z07V*47PqX5C8uS;M>AtGPiL{@9b}eR@+`^1uV;8l0?PbIGR~@4@>LzN1oJyA^aRWC z3Ze{PBXoV+n#vtkJRk)mq$Huz5hqb#YCJ2@FUUI7x!Vsk97Nit@ z=Vb~~dx&KkPzX|2Ur~^{0`9be)DmYZ2jH^+0x8Jc@7okqKEta;i7YfF87rfNlgYlq zFD;qEugtJRmQwv4S?Zv9AHnl4X(!{@u6CSk33xBmlgtKEhb*P0T3O2CT6a-cmfB-M z5ZOki60FM0T0WPBOE%{&>8SA!&Mc;wDMMH8l|U-9QtY0*G*WHm?UUTnWl>d~d4)0` zoyiO>j2l`V_Hwv3nDkc?phDCyB()d2GT%M+@k}zG9B(|?A@j-Wrj-%Rx*tX=LFW5H zYeMF8O_lr?q2|Yn&mr@DM)bXI)Fa7!e{7jAy2Ou=`P8MQ%txI0;$xB>5XcyyOf>T~ zRsdoE!jM6o@!nF`J)8j603ivM`k=s;`XGvy`cy^@CaF(;BJdlfs@@T6 zW0vWv9+tcq#8ZL|BX}~wi1_@L$ez`chMv)rR-V=q{opa4+wF#s4?iK{A*pHkSyH1T zeCGmYp5C79NNQM1I+EJthWb|WLWs{JslA)*5~8!DhPRcLSVvNOuq&xC`pZaah)IZQ zs4o)L_>t{1LL~O`Iy7GstqHaS%Vu7DQqnbA9s>JG?dHYgdN(g2(uz1Q5k86Ypx0iK zHPELL=5AH8e%O*VfVzxitxgcT^yq72^2*Yg>|Bz*l6ZN`6~xP~acV`pWcj~(lNW4r zZ}AdEvg5S`o#{ztOJ=VjCgkDEGkZzaoDEyk7jG-3FU9o_8IvG4r&y&!Wwz;y;6|9f zyyJ=KYbe=cpG;qTUz)x)=#>xJka~PEzn;;$rw+EB+UsOgPLe!gBf89Tq%*I3UN>bZle z!M;&^HG-&XXmi!Ol?6)~skW41sk3d%RkS^7yi#*p(FYn!?jX5uuT$BlYHa^Q2@w*2 zPb$PSCbMg{*{_$-HsBj#R))5%UzkAvgUntoH-BAg_G(>4HtZ^L)5g?3I5BCk|6I+I z{ck7(we5$7$xB3#cUgg5C(32LJUHKwl$!g!*DOH&yp4cvF)`MJn#3lrov>twk$g3@ zE$j~^uJpo{WKZBWB?C|OT^`WvnyB|W8x!?rxlM+t+}RZb==73>pXaB83*KY`u#8-i z!3l+Y&)HU{u~QR^JvWwSwDS?_uG<_}CpM5uR>4;MgFt}{5cErMP_-jO<*5@?n6G3w zlT~vXMzh$3*4k?mY&4T&icxe!++!$}3vNr8tV zvG|hOHkm;RP8ce23EFqO_&<@oo@YH#T3wLr^?&<-Ma~EaGFDe}qe=9RY?8{NcL!vN zQ+?EBOI&JI%+yfiO!{na7=qiMm!{G6qKE8cG|1Y+T>?9l!V}7pX4*Urgiy@1>n4{` z2ON4LMr_e6`hm$p{Xn`2E8vM+u?-}^*aSMX0n45p${6OSq1c6+45cmtsR1#g1^8b}wIIXAnBk*1BSagE)qmq}YBEkDeK3cVi1SFKvKBJi?Dyb}q1vw>Ni9 za05v_Ho@`bL^v5AoA;%@5~vAE@faF|WSKsak+vXIgXI|ng@FjAZ#H9>3ar8F`}TP+ zaW(SI7xEObcWmsP`;h6`s>QtR8C!~M_mWc!Fz4IV3bFzf(d4kN z*2~N|JYAX#x^Qz!w>kVEVaa|L1Z^0^1t47QJFkgpL`4tsS+HoH7^(MA^BnG99SGMX@inE5{F)4t?iths5#F6C;>4j@7WoA><2@!`zIq%%i! zJ=Z3_+Sw4K(ltP5|Jm?Z#;Gk#TzN1nlj2aBooNsN5u1r*15s@~8!%g~d5)C&tb`#v zXtiON>s$p8+cA3qh#~IA3}6VF0@h`azYkexZFs0(sD9vC}D&{z`mmP>0wr?2j*@di_m%R!3eHW zY@H?XGGn+<_k0EIu^c&QUIe|FEaGJj)R^6M-GN|Jsz;)c!7kQJSP1<*UcIO@8d@SI zBBT@_q3Rb{ZscJA7DPVJPpwa^jl?oID38WmU-9{#q>rf2XBynU7kW1o->0y1FzoZT z2^m2$%G{-%d~^^i5817C=p-}(*a$lz5{_5Uc@_?dhAYP>0+SG zzl(HFZThMs#FtO#w}=dOmlw2-ERSUIgqTZ+Cqc95u&B1cPz-%XIfb;A(FQGSh$FET&|6sk zAT+;?lI@0O0vX#HbXXyyreHm$m^EaN5HZ$5@{n5*IhX@5Ha0mEB*bljh5eK*Vq{O| zBx1n1hOd<=hOMi-(dVtJ*y#JJD~K3fo5_lZ0XcZ}mKY?7y+sVxWQZ770eP*1?0huF z3NwEBR+z;2$E_`fw-sB=INM@iGt=2v_84y7osq3$j~UOl?20s&WU_@=VC8{4OPh?3 zFOqV+V-l&ky*G6rxgyCHvn2szEcrz>sU^!UFumS@r?xUsD-ThlL9jaXm$8XmTeiMaPVpV0y5N3g=^U+cDo*$CCY zSCvJNwKKNeWlQo1g|UUWu+nAO*_ysC>LmQZINL(La>f=2iqnbha()s4f~m~8qZYd0 z-4=C0R-G*bh^XAj8~TApeYKugbr^^@e^3LonlGu#rXULKs>{insV*)^bzKLdu4O&r zWF6u&I^P@gnXVHUI6R;9%n&0O;_h;Pm7yyCH7S3BMgR#oDj;V;$VL4@jgwHB=R7Pz z^iMLRMuna}{|gYmiRZSp2fC7Ta4yke`IZo*qyGY&imm(3sttmpNo@^X*b$?OT}w&&k1s0C7`Y~FUK+Y6cU1_7 zTvVt7R|wHh*;3sWDR5Wb*y3It~D&`@t7nN z5*3^lyvmXZBGoQ);Snw4u!9|uJ~Xxw%8vgUoJ$IP60dT-so`z4G*)n4nSdGF(MP%I-ok4fYRE%OOpqEHSRz!%QTspBVk~dO)a|M zz^-FUot9!#PYj8rO-kahp7j55Jy}%P49BzA zF;RyO+i>VcFdQ-(#PD&~a0o>qDMySPZ*%^gQEUFga5!EX4jI|f*X=6#x-smq6J8}> zH-jQc=6S(~WIhf%AxL`_xmsU0q3+-eb7Tp;Z*jT~)87!;1xXugo(!oWX(!}GJ$mTO z?9iFn>yoK2?)5Fb1%lj!)o^fTHccP3jfx9`4Tc*bw}-_r?W&%c_3!BVEP8V2Bnz+= z=M9e5Vt7^Svv^fl3}dXC;@8e%n5=HvSd~pJZLGfe3gSGpsujFf#ChBHUaiFtQLn94 z#2y)*9eGYDFxMf@Gocpc6$zt6lrOI=%FoIyxI!3lU#B-uP zoQlJ05;yp=l+k^(+Gp0}p~0u)i#}3xYYe;zje5=IJ)eQc)`LjxSD%(CCA0g?8by~f zyEBk7pEJt7rMEZ$CzF#xw<3(Qj>WPleOw)UCQhqiFwDuw3Xx8{3YpeQ$)#j}qmrMH zfstfXZ1X@qi>zqG$EqhKu9gxlbJs$&cU3$ttWuAMarv@y@$)V_8KnGx$JP^(s{T( zV80YN!0dcvC_Ir6w|cAy>r)|#)FFw$`Q4u;brYM4y|4}5&m{1|wE%CPGI5R4R3Cb* zS8--Bo|LlN6jr-tsgV{y48wsZhu zi~U&0ulZV1O%(H5)R)L1L4AFK%H2uSH-kgn0xN?00;aNg(wl&ke0I5~ST;C-MoDFn z@Z)KS@yd=y{wJM3bzQ4l-7bC)+dN(iyt@wV;{6UkPvSO<$5y4|0?CF3Va`>PMK-j6 zALsUX6$qY)9lQj~FtyyF*d(^rkX>pFxw*XY6&wlv^Qaf=LTW!Coh*CL|K>jx!;nmuJli* z1W&_oKuX@O6vTv}5u(;T1u>B`qfkL*f?a8AfNh#Vw59YnFG`MBnKJ97RVRoE+MB5| z)WklI4q{^eNQw!_-l_?zooKmsZ6Nlt+(u}Qf$5(%i<0kzJrfCb0nJ^TUZ-y2jcfs_d|ygb#jX5^WN}IV{*QZb8xq{ z9LXf=YP({C2mP{TW)03k8Dw22_w<8R=$mj5h#kWNfw=C3Gs)c#_Tj^)FA>g!2*D0# zlKKn}$#ryjNI*ZEC71!3Gdkf+_5gYt&m@7p4QK+nZCa;URLk0PqSThv42X0sQ^+M# zWk4vTi7Z#U;A42~1s@6Pm(*m$(4@nK@`y*0yKKYDlb++6y!4EA0-LPjha;OT@gpLe zK#i5v7(b^9_mr8gIFI?@8EbBWJi?};6Nvm_9Y2;PBYT@L^s{= z>Uch_4!YA>9E69RW8C=p(5NrRAZn2+vshP4ky=8`Z@5bQ5Utz|v>dkVrB| z#=Ow@-15|6hF&|R2#TC}uPJiy-uV@HZ&!U;;k{O0UM=rs0qo6t(L{syDn?$9|K&;{ z#i$PtRxFX1;K7Q1BK`>t65V zV1kBKai)@#IoM-zEzS(-wnOO#khDXouBU1Xn{Ai?4&^36VYr8u+J+rThjJ6+B)MAG zB9`i-O^i@Q*c2mWL#h%tT3M~wH~lhI0#T-%!0rDijKuE72n zdx6j(OAQKiOK>iL#}b(I%g*$v=U>=_GA%6xrT+u6A{b=uucrnnJNvGME{KxYCYV_Y zg{>cPJ66_@%<%hN{ituPkHI}{2GF--0r^8e>Wl6tM+I7p%N7Zs=4Zz-j(+wf$pBk&5~zQlwOY6)Bt%@Qqg87{8cFU6YQ74b?z( z;Bx7w7OPMI#Gcn6EPArU0+Kk#P$YvK(bqY+!5-m)g&lj3zMge>svwCdbd8@`fQREGo^~~H=or;LLTQ!!a z|7>X0*v|5N(enleNmMLL~qL5s_dbb*Q7LD0lBC@u0 z-29T!m@#imkEse6bFfkUKo4d7X3PjGX3RKh$I9DPmpv#&3uPVMK*x=`l4E7mWom+T z)cl&DEn?ylR5Bm}>$sv+5=xM{HZbLKh^!8i;zqvYa+m-L%g^;Jb=(Zb{fj!7 zv#PmiLrgh7nYHbLUbq}C;f9G+j8~hk-=!UIowHzDT27&n`fSJHFr=Rixn(fur8#*| zz%Wz;c^6=8i=*ycAbwTTB@%+{l0ma33cg~J&4ehpEiMRcg1N1>cb9zD`^mfbtW-e{ zBY39lkR3h?Z^Ph}XmsK_@o9lpUOn%Dy)$`wgUi$uGr1 zm;92;eOV{sv9VEU3AW{z%Z8&ciT29Y&?ak>Cgo4v=fx2F0 zLgB>iCn({%ZpUND9KG}GxXdMPKWWu*-d5D{Nvn=?)5|edJQuNsM#)$xhc z@dM)6d>6--Ns;jV;_jr(ah!v*kQT=^)i8Y9S~(n@l5l<9L)6x>)XHo5&``(Kal8{; zYar7)AIQSZTDiQ8mr?+?lR(HN3E(a`F{3yzy;hY#W$=wKl?e|lcL=#+Vu|4OOE}G7 zrsp>6vQYStTnB6`3M=wt8VxGx#BBWlx;tMH5jtNn9*|~9fhXL3s^9E=Dmb0BrAz9z zGvTPM^o^-fCv%gMYdfSTwe3r_`Q&TVG)V>lGC-uSRt9J+F^p{xs1On2s4KtWzd%8H zth#A9Md`oF4OA+1O)7O2rEtVRG-*o_S5akHD|yB7L#E9l2w3qt~Qe7Xe7`OqSWPS>!ai)1Cq^OlItR_vH>wQ^gVkmWW` zj385Zqjh3ahGMr;KSDw>eE_xBYazrY^XnxjPApa>4?C{xq6T->MO_Q|!-&E}q?-C# zUSCj6nBS9m1#?U^YwxcZ17aE-ck8yyEXS~cMAQ@${DTvCw5!3tR!~%JOF_{a46%rq z1g-bn+9b=0(TwA=tDbD7NlmJZZ7HaqvyH>}&F!0)TCuZ%ZvUe($&m@;?-J-(IG$w| zi|-wi9GMWsRuz>Il)0{5ubMIobkPr6pAg~%9(wGS`f|03hFbGYG-TpQL$EQ^!psTY zAp0y#2->`cMmLr}jGIChjCM7Z*iI(0#&Co!%Yq2rwwk5dA(*M)bR!I=y#EOMm8iR9NTII^%v%12`-I!<__r_#Y;HDct{ z5F8m@GPE$NExxoC6L~xYJS{*6JT2~~d5tB2uO5~l#A;k4lW}ZIt{UKW*lV`rDCZ(c z{>-Z@>@{jJj<5{m2ls~A29x@Fgu(EGi@S;wMus2U>(0!sN`|kiY!AzRaG*|KGNt5J z8LpG)n(cddcodNz0R#*hw&EzRa}?|QWBAg&Aw-&_n`aDDA0R47rFP|YWqC?r&SZviJeneB?f+qD|4NT^6Rul^Ve zlzLAIRdpH~T!2+SQz{^_jwK#!o+@RK^xas=WOz_nKEv^;CzO6nmuM*}b22X;lw6rj zl?Mg)DfeYj;t5I|A}=>o@s|s{{%7v1LZT@V3Run6>@dmGcGr;MlS_AN>4jeKmw?ml z9H(Arj_JqYc8(9n93M6}5o0>6b-=A&&pPPyVXXsS?UmL+WTbHj12^kZk9H3aHjns% zJzq!{pzuX%GhcMp+1d2G>t#jh=M*82G_!^8jq@v;Y0Y)V&Y! z>#_FNef)Z`{dGS*TW@|^vk?6|PeQ!vaj(SS#~;0DP&w-puo(Tiz^|%#hEL$u{y{M- z2x0Z#h=KFXcNum!lyJGcq?5vB?hvhzf?sYYjmxty1sRVT8MRgPMi%Q!a2I6FbBjX8 zj@d%o<&7@Nh|az{az>&qGIY8wiliXFxq91AdDaV9OaOnG{OPAc zVj|CN5@ptP7d(HT^UbElA>H8kU)@mM=aUS+Msct2Og72PNAt<=W;On6n)4$5RyBWb zUl%rdnqVewBatw#{`++M*ld0Jef7M61ykS&8FZtA|7A=s3ymUa7*7WO1O@x}D9#Fr zlBQZ}wBO>O!^^J=TQgQV5}HX$P7$8oOZ&Gq|M6b>eGN4LoaVv*jvpUlUBy+h4?xSf z6V^+sc~U{3*+%#q^i!$>e8-Yg65c(?hef^L`vz%2{>x?78Oe+}_AVoS*%#Jv^)5 zwShmUHzaeJ{<&HGwTDxkbna=kAHZLk4W^%_b_uchAL+kc3kk3#zDpN-H7`8*NzntH z48v9z5jxA{ZXT+v-|@}V0*KpFZ!b|6;!ZbWcnhr zc@K81bViPPrneq;87fA;UFRYVSpEoXZJt%L`a_oH1AwD`-`}~NIxt{(CIGK-rScTe z>1s+iGlrEPzW|-ySkrz#qLva%j{AWn&qbXALthZb1F)?Upe}k}>v~lWx>1k+y=c|I zrtTNV3+KRH;!s!9zpClyrxtRJGY9z{r{V zN4c5>Cp6)!>IUVSyPEeKrwT7Q!#_+Z_>k5#qmrzyAkI_RGr>qa``0&Sz{& z77gDu-UfV_J_J)NC#T3pJ52FNcybH`0ITcw!PlsMR^DH$9*5d&QRRylhO)7`lRK{~S)Np5MD4;jl|TmOkA-zd#CkRyi~e6r^g4(cts+~ z{pR-{|AD{wwM;F6$KQ)QSlp~>_6D$woYUVYs!`i>=HETXcNVlRn4=yHmKE1$@yzj) zhQ`%CO2W!}YXQX(d8^V*$UUU@oQ&yNLu|hsJ8SX?<>Q_dnn5Tl;oSDF(Lp6#MM&Lx zFTu#73I+EpH6yM9gk<2t3y861(vvIdBgE`Ye+7b0H$xXyWQC&zkUakj7mH@zyzuiE zi|N1DI6)Uf^yf>M77*oj)bMjh?I@?e02b(0=#e4E>ya)%mq1eEKr%zBoQ(j~KzrBo zwOTVF^qu~yBXk|FM>=+@u9JZgN~>PeT&;QZ8aISaywa`f$nVG^%yK+Els1nicmFFv z%D{&Td;qtF54xSU`8Xq{ZMhfE)UEB zHx+Nq*AxEo+BOtD(qpyP= zg{DKB)aK$$hwzT+AWE;a>}W%yq79uFV(vU0bVPHr?jIZUpC3F5{bqE!{;Onos$l`@ zjOOb?rb44^t~<*?w4bbJn@Z5W5-T};J4b23^tbKBONSZD_?sbKfkE)?Tl|T(Nd7m)yCS{UJX?Ho{x)pnR`{7=Dx=r-+n|xKbN)Aq_9O4@ z*M37UnhPHsv|o8|zp~)@dhwpW)PCi?{aQCL`DW*1zuRj+>qq;&YJh38^Gm;T?eaT6 z+V9MSzJKW7JzXy|=+`%Uz(rF`7GtQO`MLg#7QJ(l2pACagsZpGv?b3I>V$8=Yz&T? z{ra#Jh_59_ZgV7=z>XGP@8INVYSLlC1q-cnHCZ|1q|-Ze#XNa#RGwqib;g4-ytQac z)heGfT2*5FQj7Be^L?5sk1iR6+H2~j6ep1(ZrFSX62+Bb4=X5iPm?Q=O z$HWefo6NB+g3J;4@`_|Gw}C)E7MUAs?!(J~j)=^K6Xh;4$0YE1grv#CH(Aa0GYk9> z;V%vQ;ibT3el#5c_Q^UN8|aMAPXD)R@^e*H2A^St)PT*0^{VM3b&!9MlsTRXE`;wk z=5T(GT!+pgkG-|ftqhotCCWAb(?!ryq6Id>Pb1z@juo=}{zH7HlRp5j)hA1Yj7G8Z z*QY;T%Mc`tDz3i1SOa}AOV+wiyx{Pn(wVH1WcWkdx<|r_l8{}?)anAPDNC!0H(qTm za7dX&bxs90h4x6~zBlADB~D#Zg3d{Tgh$n0os;LwvbGctEdo5qGFlRP1C=xtz>e2x zNccsp7|nCcQvp+&Yd|MdOe~Yk$0(<+@hbMl!|W|;I+|-b7A4x6n0|!1)WSk1u_SpI zBN38PuUPi3i}~@!0@M%XHbkIUF3YVWBa&kX9EGmSxj*kDWocd4zP_i2G}0REU%ra=R;Z+^>qNlY}GTrYY@B zCenX1qIpNIF^@ozu-XW76^mf5W}NmJ@vvE`@QF%yj_C~I$L#3pP?KRTcfcRLH*FAs zR(Ra$4b>6y997uZLpe_@;eAOpfFYX&{Izy09pI$p`VwFQU^JA#q}7u;QwP=krD3%% zh(NkSwH-gI402#|Dn#v(F$-C0O`K8k?E{~b{&kGEKj!&$JQ?%}$dq{!ahKk?7+XJU z9wcY;A^yz9hZiPCSVY9Uudhy#ABE~>ejkz2!ZoY^7S)43BD?jOn|3zfsqbCX(V2CH z>XEw!tY;mawm%=j_f;Br0S}QRex7Q_s!h&g>UIrjp@4*X%62x`B*4St`qLj#-w-4B z@i=;RF-_ni^>}qecElC{G2G^(D{y!R17g^KL!Ro4i)v1vO9PEDtEXwOi%o_bBFX>) zEYGn1or>!>Sq#rL{rBk-3;p9Z{=!&GrkD zl8FpLAUOoCiK5Kbydk$Kn^li1lRe#oR;EFN4VmU~;lvHJch4{J@(h1Mpc!dBV58tN zT|G`MdYTcjuUVc7Oc|OAhBaa!0CQ?Nhdx<@a5zo<(4?Ca7u(;lv$HdU^t13r8kq>} z@bafC5{@vWo{1zKIiV7!kYHs(x*h-qBLy(h;8H7$}ySZYGdt%MiS zUJ-M#q%fr|UWoKq%r&L8m}`1g1v3kRNB*Pnh71sI$*h#cTrK5=?dlqhSYQB2tHNq^ zNtb?4=7EF}m89HNq>$7?HL!%=t0o^2UH9*~PU<1L6s#Ok;pRtKk$OG0e4U=fw?K&= z!NbCS_p^0XFX^flw;^HW6a(1F!fG`?k!3N}S)_fBl-3dcvzUSz@7d;r ztvpU`*lWgb!vQ0Zz0d=%Ty$}1(NyGIGq?qOpk1z^gkaL7d_>eDhF{<`u)^l=(Pmq) zlwDaLs!IztAO39dwt}Ul&%j0J`k_5XgZ3QZ*D*{FJdP}J3`!5}fdxwkn$7u2abAz0 zX7D&V{U|y3nl%g33Si~9&;yW_pCRsOS}&HYfe0oJbtep=Y%l$$uwDu0 z{Wg*q4Rtu%d{0_L6!D>At(+e7DRG7&K|-5n+QQ0=3`3SFSz>t{^5m=P6THp5P>%6- z$inT*Y~q36%KdvqO`x<29Sz_Ql|nu1M8 zK8B$Lx91*H9}n^NcL9ThIw;GQ$14I7Bj4f;)tO9(L?YyJ;Hs9>p{gGEr@5*Rxzbsu zgj6FnzFOjmE0kbwWRDW}{IkoqktTmv8y~+y2`MU<_Uf~jFR?Nu-?de31a$l z{v=Yl$fQ&%3F@}qkU=spQLe+Z2Wb%L3z}I?GtFcKqF`qUO$Fs^O2kLgNIZ&|0qLz+ z;iRMvAu2Q@ZY{zi^7m3zzIBC`QX72dc}$MB|7z*?Iy!R_*gz<2&d7gBbCx97YR+0P z{Dy1(j5;OF`G_@VmD?!2pyK<_>AOr~Xx2~hA=Kw(`Jd0_5uMSz{ayS$*Z(VgpIP(v zCvo}w>DT-TU3B_8si3U;WJ7dHdO2H!N(sGOf(^x6y_}rV%agR7#s)1C^);qjB6opI zs4YfsE%2Y2Q7#i|?jn<34yIRd*J$F>5~nUL0j67#xLgtDd3PfqN|mmbWgwTf!d+#% zi-7A@y5nrmBDY;qM1}&7PTw>G-<3=2^N!rJg)*Fw}X ze|ZM1ybSlWUbSoRsMnw>-H`B!Z9%3=Er11HCG6J&0xW{-Ux0XrkJ=X~-u1J1*B5DW zk6Q7r`8NW6zm@Q`({J(!QHV_w;o-H9(R_=xLqQ0lA!wCk})HY>P&+KkD2~`Hk&j#~7MBpyj3RgG;^x?QF+VVL4q zl$%<2Q%jL}6!jRRWj6tYw&y0+fXo7G@KlEYtbKI6G9^j5E>s&9>v4EuEKa;qD0m z667$GBm~%90#E0l^Ofm5vK$h!_7$}Lpz#zG_F0wEeGgR1WZ3Kk17PNc39H?bZf^># zM&@n%Rs>dS(?aqbfRG)dDa~JW`65Qzr|N1La^Tc=7geVr6IKXmOmwNR%*~omdYHM; zch|R9!20hPm_(`M(ABpipkY8oQG{u=3EG^g^wC%Zmjue(3Gi-Y-bnjiZ zTiMnVXFmVKuR+#`E-P@UE$%H)cb7<-L&5;>vHmK}HE!rtil zI*ioXlC(mgN8`8}XhbptAT-e#Z=E96qQ3Q5ci_ajiUTNLXT&BcgOkl!`_9@kU6dMx z2P_E>+E&E?*;`M|lqLx52-M9-u&_a8ExXF5L`gilsK~X{2o_cmA0|O|ClQYY9s}|V zLDUG>6gD|+oB<~=1%eX=6U>sPnscT@G9}uK^IN|P?7pN zB(Ho7zP2jNh{6m$&bYd8B z_^+raQ#SuAU_&5cI2FV3*)4P!cH*oiZ7Q;1?5>M2fox61OP(7jt(!Z$K z>&mN)6mNk4vl2T+2vZ2OF%soxEVz*6vCz9awU+tU>x`w>8B3*E6l{;oSmqi_-5pDv z#-fQQ#p!US@*t>X9fYs^%+gOk#|noz;!WPglEp zR?G`vt=-(R*(v2^T?GZ_=TvUSJa>AMspb3dHMf%q&!A2JT7MsBcKAi_`8If8`+1|O z6+Eh2f(@nBJZ%-ZP7d6X zNz)Scb=!~H>Ep$yx|+-xn`?DliyCJh*ACEd=Gj$$NK58M(F$zCa(B!GCe|x@y1ls9 zWc=qc<;OZ(Xmq>#QSH$W7DTrbHZ{}uKPh92l>GoZcM1L3&J*t9QHT`4{7HZg8y+TV znd|qYdqdO#W7k1FmVUHpXF-3Zi#AfI0?HH!r4c)M)?` z;ynP?ycT%dnwDy(wNUUUJF<;Jb1rC!v7W;A(OiIgfK?FA2h$s1hdSVR2rxw_7A7)C zj35!KQE6M#e+0gXZ=1(LHQntKJOIrx>b_1JFm?0juM6lh=RA!R{M`Uv4L{C1u+^*P z;+s4G4TUS?Njt@xY%|39Xt&w0TRm*pCil0*$M?kJHn)smubtew`Bd9Oe&F78y%(*^MSI2Y(Teg&=E?e~SW>O^(OwX8Oh}>yodG$BjVcv@`CEPu!G!Nv zC-Zk%KGb+0d{HHfu~7wbghSN0Yx)?3m6jOsHrhh2P#Tftfa9*MEzX3a!jC()k1Lej zwYR0RsudCYT(cR*j{(vVG>lX_6>ZK2XS3WSk(%7iCa$5~!pZD0V1H|m!tDkZ-%~*W zYJrO=45ahVPAZFizW$R%-Ec7emVOOvn&tAB+_ju;=42B(O?{%Oh&K<_F-L3t@#U_c!8W(91 zHwdp}#G%dUzs&oQin_vBtd}jUvTvzl+Do5U)K6Xwcw#)IZp)d0t?Tm$FU@n3V0KU; zJr406M(}FE8Bq!Q;Vh;z72-#tFn*J%=%_48@VBrAfbR)CE~sDq>Cd#_gae^t@%fkx zaMOnoQAl8WzArWDl{Tc(ve&<4*G}cGA(Fhp5^xa@)@>Aa2TW!)4?&DTgDQ^8aWIC5 z(5gbvWt9|dT0$z>L&h!q#)erFQ8;aya9l`{HqpWwFHK%Xx;5U8itOJhC9GaJ-Xv2< z^i0GStdZCKlH8&|+7uvpaK(1wUUh9JuFk1zF_VC6C;(?`%dQfqXer}CDgn5Lwt8Kr z$mvUpFrH+>@_pq=@xZJof9w%#7a}m~_+#6yXn$<-$RC?W_+yX4+y=mfn93La*s@Jv zw=m=C$C^acXw^f}#fEDhm;TsKJr3Glhm>anjaP0RD_7i>6M>Ra^2%k>2jQrKK9T&f zrQ4IK^~bjVHo}J#dzfClg+F#LJE~|MaMl48jW<7SucDfzKlXLusgjm^y~lC~7%cPb zj|~Kt{@5c(wrvW)Ci`QP9ocVv7Pc};?DlXTE&Z_#?(oN!w-cST31}lszv~MOJ~2+o zXUQKMs%=%%R0{dW(-FQ8lV9w$hi{~rNqDzOYEcqQ2P#M{QwHEGPAcJXsX&-^8H!MX zKJUc#U=FNbD%w?4)BFH}9Y%*AB_UO#P$b3nRR}_{yT>krVnx-U0Sf!lE<__s4m#^a zQ_xLXjtKQ?Q1OwP%}8*wJ@e> zXSaftlGs^{90J5;Go?H-eb`Fz40g`Dt8_XkJL(%t0PU!QBfPJHNe*gN>&7Uff~+AI z2zTM0*?+H`{!EqUUc{uGM=IE|tW?$R;ON@os<%Pqi)Ny|j@OHYiT*1e;I`Dw%1Tl< zsB1L=6M&3L%pVpry)jSeO|?2rPtAtD39-P=)@lhQS@zIV%b>hGz|tdFT1{-UdX^u3 zLr(KL`8)MEXq@_qbarj=#{|o^p*aZgup#S> z(fOupPoNBCNxG~;xGaQ>AVKz^h^4NfED#7Ws1PoerJ#S>>Q{WaysocKmwVOix~``L z$R*bneKkq&;`Rj?q#}`~_;~$@SQ#;LRbY+d9W0?*j#o@sb$e<5la3?ikc3&Y;>5 zib*-5v^j?>-LTGzdZ(Hy+qgj;5jw#qnadd-7WCPClLWDqz%t>xkn7w|m@9-~ZN(ZesDCVR#{f2iPN3BUMQ2nL>3T5~NGd@9kWYWscS!pu8yNi5 zHbiM(V$oe&kWbj`?1{bsH3e%5HYvU#J^)iMw;Vgq5~d1*Bbp1s#sW4c_$}Cswz@PKLVWDQy^L=Bjc)QJeNy+nm13M zL&witBIfhbzdDw7I%b%+e52Z?sDZr@HpLOKc;3j8=jCMab}}!pz~9MF)}5?~r&#_p zq_3xh%E+8t7NMx{q`Y}C#1ZWi7{2Ej?;svy57f zn`{$LKtW`Ciad%blTPSn7cNhC4A}@LD%uWeiK;0R=205>UznVe#eF3thOyjR(j(|W zzxqG`#Met~Rz<}!i6R^!;2zPRrr7c7d`aX%icx&LQk;c0*-oeO)XuI#`%)oqGqr6} zXq`fBO9P2holen&7+wbGtOJSw=)C!(LZK4!*dC#i8WVSZVr09&oFCNlymg5LS_7e@ zvUHo?O|={8NP4 z2c)I-rys2p$#ZpPH4nMEG|PKT7=8y5;dD_=)cB*S5r4jl@)M1JwbtGEqFl?_Wx$eX z_J=D#RQL~7;ikGM2h@bG(ob0=op~zw25HVPHs4}0fN>r~S}9psed(z$w`Ls5dlMaeE?@!fi4e23h{MMi-@h91x_J_xI3hl8>oBK*0GRd);K2}LAk zWo!|R(&*n(Ef(O1(6>|{iuI($ui)8YHF?(!#b4n~qaz&dLuZhraRZDnmSbBmrkKd9ITh{W>-rh=_xM`+D^=V|25(sy zG|9#?#Ds>!Mu0aci(-y$N@ixCVKzC;swsI{KMZF+@DMY#?;+9iW7W-zacFpi1CSp- zC($IJ;hQ5PvO~X2c^q{8vjaFHeKkf^8uZ&C+N@{$h0xz{m|0ZY@}bfy_&P~OK8kKg zB?&g8fMyy8p)eP;HmNOn;*AX6UY#rhOJhpfM55mjN zrhvc&i)h`F2ls0A82 zLcUJ3>c(g@ZKBDh7#2(5!L`pEXqyP!z`N7(H?v0TF8k4Y3 z!>Mk?hf*NK?AvVJ0N`A3s9Ku5*un(1oUZ%0#AnV!3)JAaX;A?AcunZZ zGy_Pf^wU}{(LmF=zg26h?&8_Cd2(;XUU-L9+I6a5)kR%GqRJ-i7G1_`D(#JRyr$B2 zNOBrm@tQ(LM2hqd_^uuI>;mAuce?sKAB;0K&|qrOh*9d0Os5WBikn%=D1bKi zu}Ov_O}oL1nL(TT`p&CuW_fepn{kL_u~n}1DpXe1v^l(YS#R#ImSs>;$}>(e>?rKd zN2j7qHup6#o+1qG{EVIbR4xuQP%?J*ca_XXSN&ah0st{o;76?)!(ta3_OtG@00VrJS)uNT}I&bu3m2e3tByoN;tC4dDJ1C0FbXiBxQ#yCU0r!-AwK`OGg16 zM4c7zwEqIlj~`%ln+gD z>5x-2pW!E*V&}YrM--}8=N=#Z9bvSNP?B&P4=VZ_JV<;uK*1sB*7$aFJWjh0!uew) za9WjOw8p#KgJ#T5I%hf8n_11QoLo%?O^yDLY=>;1^+Uahf{wJCKg33j@Pf=ban82F z^SKh*Qp|=Twpbt+;t-+(EDiHRztQF1l30QPep2V469jvj!>_!nU?W;WB#Y=Krbcg?PyF`9V*1A*`|5_*SHs|9mMT4Z3(=kZeH!40MgXke zkVIff8hjP-v=(u@o_t4Dj+5^!fN#NEDi3fZH)65oA9+~S%hPp)5?@JwL_}t81ig_W za@iz11qQ&>mb`Vg1^9RfO9zjwIrdCJnDrSDzA0Jq1mwBu@Os^h8WNohU#AtxPCprOZBifiRqjAFqhb*$OgC7yz|T+NlM`1OyDxKu3}P zRW#HFSb`ViRA^W)(a=UMv9%TrrNOPBAwgp)m(h@Dy@7`8lC@~q+Y1f7@c>CrXsEW0 zhV>E+-PTK>VIl|UgzN&YGxg{o2@S<)W35SJO$e#oyUQTtuTdaj)TDz^nlI+v7Wdw+ zqacuWP54MhLGXWIs)RuPcbv_1;?>uQ07({l8BpS+;+3E@r5_t6 z6Puz{>%6k}k*R4quOoAacQ~37?D#$HZcJDV#zO6eT?PwvF0G4&>EKiBFYUs@1aGh% zy8}Z{;O_g>RV@lecs$O(%E zSd!fn9oV*oH-L&p2PPf5-=bir%>)wIs_9vR3H#o=P!Mj}^N<(vCJbB*nbr*uJymPR zYYw><;4bk&ta^3TY*K}pAht31)tc~uAt%@vN~@rQx}hwvj423UHx}3FZX(h#e+cEE*2-mhCk`TBgH}F;rr*d7Pa1wfa3-yCe(E}H9tvN{LtzzbFB*Qd0TWwFmqkAeI0$pHa$$hiL!mpksS~T5sVNUw3<6K{ z7-EdyLfM;`L+=jT)=H88I(c2O3Ef{M{<9u(k9_H=Spg=8ahS2EP|ZM6A_{|8jO236 zYLG<2F1$|a5h7M%8mtAQo?zaLU@e%LK~KU&VQPSl=!F%IVH3@SHkCYj{F(_L-p=cDD=85x+p0mPAj@5xHWj4xbslV zzNgW5gpI_VJ^JOyJ=HPtnPlNmF=fiak1O@(lCcG6#~45_kOc?EXvSyvL!OB1wsAf4 z^o)-CFKTd#6bpO?^89fHKRyF zbjueROy`(n@Njg06kCeu6A85mX)S&Q?Ep{5%@)0pmvYHn_X&vi0gx4_KCnCCqq`Fx z%?Zn{XZdGMD03P1Zjr(ZhW+H&0`P*dECGek8XR}l%_!Cln@}1)*8lFh@m4@uHzt#o zHPX6SgW7A|P(x?kunGhruNwkC zVO?`tGMgPsD=P`lhQhOnGlT;miP8vp(%_KVzKEmJ**_}Rp42O;w%MsfS32;4_OZEu zFd@13l~vWFDxqn&x~K}we`QsTcK1qxhkJ!+`pT-B?yicZ6IFq)udJ%s?y6XRu1YR8 zI?pOblIwhF^a{1(4FXpOy;!LDBXm!YC-D;+8wk^>x!>vuyA}avLZhw;ENmkYSi%et zh>!_S1eTYhXSW>~YZ!EL*wV>iODAQXThht9Wn){#b`m(7d%xuu`rBBNvxTViU?|L=SlH$UjdOy-*ALEfj|mjbg%H^DCVbM?v~;9M_n z5VG;btTQ@EE=BXy?}$6D^L8GFC>jmiX;&fF80Q`(p1(o~K(R-O`<}Xd8$fH15+A)n z2>`lBi6^d50+{bn;yjaZxshvH1gm6pO|W{nE%6UXIo8hH3Em18l%S_Kh3`AMgriZ} z3y-O*u~PiEnCvnmohgQsR*6wTl2=DdW|m~HsHB-MMQ#o^D>X!J@l^@gJYbt)V8z^( z<)bigAx^JbKKijT0-oZZS4y0o6);0B2DL#YlKwIGA@BRRR%O9o`>vA8K-{f_KCI}3 zu=jm3I?&wnp9D^%e@H-cKgkxZ_A0aUKkQlNGbFprmjOdMl6vMYBvWK0NpYV{9>1nK zeD}KC+OQe#V_EE*$vd8hJaZWuz_^EVue07gx5_Dij8C9i_g>2nM2F#Fw$Y!(!YnW_cGik1W2m+kofW$#^}HM^=h-~ISr=X~e!)iWnm z6|%ogfK!r4(RvM!sI^W@LT+xF;K+5L!`o(z>lkwDaC@Z6>JrBd$)QukQe#_vjS@9V ziIJo=TuYnL9W_d&O}9~l1`Q-gK}QXewgVO#Btjtf_n&jE{XNd9N+m!yw4~sCd++t0 zYrfW8bIrwFnK5yw3s`&M(M*bA%*hVHRpjJu*4OewjyKS_Jn2}%pv&8FpIQ;E>wJZp z!!oh;^;QgiS*Ik}SSOLwFeJuL?8PhYb=?|$!m!P!rMez{+KV|r1q(jqUKhIwm0nAK z#jtO$9Eep*Y<8=}pnl<~1P6jEy~Yv@Oj(xd-6=~?dlD=#*vmJIx;^c!FVF{$AW*G= z^Sb&)*VQj}Pmky)z?8h`JKlX={SsxZu2bIK<+Ws_3@#?rS6xuOm>k!6ZC6(*gj_EU_}da(=W8Q%`D@k2IXL~>re*y`p)wKBc9`Z_vcxeip!%(n~L zWP4GyY}s&~Q?{2>%Niv~2M*A}E8@qOQdZwym1&J)r<`?017|#JQQ>YThWk{lH-?eK zBhVKgmVde5zA(!*P_Wt2F(};%dYqv~{6qqj*H%5Ym5%<_Z+`IIr|^S*qvPqDsScHV z8$ZX1AR&9#anN=q(F{}-XI~hB2~abRfrGXHB|kmDcKGmBTKUj{rJ8Xl%TPaA{X+fp z>RMUmb1EyU>gxGS^r*-0(6(wdyjr?-HPjmup*Mc?mRB#-8$WN*IguIL8?!;qi2gJz zdC!0;@liilNgi9)@Su~d=b}KkfBXZ*!in(@cc+)DB*Qi5fsS3ZGobTb#YJ5jWPTN< zgqf`cOKk?TzLLh_O_NIAueuHie3<_-LiWCNzRY`a`s-l;_@X~*;nPr6mVaIvHOiuCbL z<7@`=tRRICa+RAO_yzAAejUXLNRQ-;kNP>n?D@Zt0~JlH0YpdpUz=fuKNS;J|;67767+2Bcb*cr+d#55I zKHl_;fFh}jy4rWFw-4r3{)2USN4=d$Bf~D(ww-t*n!m1Dj;Q9rd>@93z&)v=0G|+xtPKo{sf-M}$=DmuXmJcja9(Y4Weu1? zL2#5<|LRn|%fZLn-MpR4FP*5*YrY=mZ3kazv3^1NnkEX8<1C9I$o<$^h5K8uzL5QX z=!|pp=8-!m7-#}k_YHRnnU{ty)X!k}BK`D+7Z`>QUpz7vad|Y1n3GR%_NuE{WfKdQ z&Q~n^Tz()k6pCTE{YjP!r!Z@UQ=dB_8`{Y=)GA#gw{nBXZFfn>T364{g5LgxOSX0O zYssB;@MyU0cNu0PRw{K^seW(W9IGX@cxm0=sjL+vZHd7FI5Jc9n;{PF7&R0m38n>{ zND^rb_1fnyQUGc)jHW6TdgEK_>J1Et*KcP?Tj|S^+9@toE6VYP?}Fch&$$Vfd?kMi zm|7tg&>?DMK~>l(Qu+7-Xxc;QT6>hK`2?@C{vvBAR?F?vOKjBGYn4mMkbe;yEZ$=8 za{KOtV{oIb)F+IEMe?@PydCB3+~(~FZ#&YP2688~ye1-Jd-%ol(S$$;CSP4JdV|nk zGK7n7BOc)Z1A#$dZdzO5{ zla24j(ifNa^ATeax&Xg$N8M}!RE?nOzLqiO+W?ne9b(xEtt+szv!N<xRSCO6@bCKk>U^(hv)2TZN!^S!ZB|VK<4o!> z5yeIoD27QIW2^w3M-^CebbhiDF?}kb1{Em`OEQc(;$lM4dm}zgOhuiX{6g#5aXwM)s1h4Hw@PeosY+~6EZ`JiOwAkO zNhXQaU6ehQLriEv=l~5->}m+&yoMNFu$~Z*%En#TEH-o+ip0T-Oc=($v_zixoy4~G z>*nVGjbodER7fH1z%bg00MrE$E}dr+a)fRie&L^^Ta(|=?K@Kbd8LE4#*#%y)zzR7 zY?nhFsPp&*G#2%Yx0skJ{)> zAEk%00cW_ang_85bJeV&Pb^bjMt9ip6l)T8%K-~&(s>CXdEby+bLZoTwV;==DWLw* zqo#j4X+NqKg~1OD3!&&cU6BN)D{vD7M!TBRC{h`ayKTl}Xe4$6qE6iqsWjb)H6Y5^ z!*s$PbwlnL>V}cfyc8uC8f2ToTX1+x+6mq$5R#8LJm{`#grPP@ARL<`#}39CX`nq( zn(a_Jr)e07yhLNoJLDxAYu+I*fuwndLyN}ZyGbYdx&@I;^E=%r!A0Mzi2AOy0qwCV zJzu2@CY>d&F}BHEdhG8I+Ank|E};!yl*w?DxcCv%1UI=Rcr598)g}?V>FTiyn@lm4 zW*&0ZlojL0=UXazM8}L|F+vz&5C!$U(?e;KbDRooTI!xY* z#YlP6VX{&!+U?ERxeBnn`+mbo7W)62Iz)^E2DDdcv1K ztF{TgwqT6V+a~zh3bXmZl-oKpewfi}nIU1mKJkq8_P)19rOVEm*qMyOin+^Lyayc5 zQI$M%79y+85v+P1BAB0VD(+^rFUuoKc3*AFWJC+$u1^62Zl2O29XtPH1(d+j@-bssZgr3nsLpmsp7R}hp<6~)&cd}>9_9`^VHVI!8{kTMBsD@7vJuEv#93GU5uo8z+Tcaa)2(_uV(GjeK&eh3&R~^>S`X_ujket$xK8AK4|1+<;Ak&FL8v` zpe*WbymC+k7jGS8Xj%V%SN8I|RH6NO{Z6f2ts;yC8&*VqR5UuMx+sSgrYf&~x2cPU zW0^UmqpBZi^?x*HhX%A}e@Sk&Nr#~cVVC~E|I>v-dARwbC*tlAA~O#^r&rrOf>`tL z@AR6si!`{jUG#fOm<{i@AGVR$E;`AxZ5N^Z&{0uT|7VIbZWlGXT_w9+*@k;1H-AJJ zF-Ox+fo+q!MD%!r-Icq}P=Y~iP~wR*lt7?vupe`nv3jqb|9;FjkIxg+ip0Y(diV?P z`skl;(u!4JjKZC%x1#_;d53M9aE=fBr>`$I-_VQEeSA9tx1>X4BqnWkneD^sX2e3D z@a*AJDBq+_n?>7pfPEBu^$#+Vt7fb2gOMTUbh0!}+Ze*h`K?7g&~6a9*mj06aP(M| z&)d9y20KDF%)`4rVFApC3*ndI(9qx!A0KSYeF3OFiE)=$hkW$~Q1KD}_I9<>e92uqb zcKk34ei`DM9(To`3$cy+kB*jox7ME`-~)D~hAiO7Nx!s~_Gjv-<{1-^zg zo-lMg_KqZTyI}`984ERoCzewV70`pa^v=AT$89Umcthrfr3ep4fhEg|?nBdZQof ziP_tK@l0o}W(E94mRjk{70vHP1?3 zwB*I;CmsU;t90>3gGE=y4$SY=GBWX{QTsv&C&s_!A?uwIh~y5V3#HDnodr0 zaGoWfH=Ug3;02cag6ZTm2j^R|g@zj+*k}$mf2Gg?W}cSqdxh32;#tmAtj{)Agp0ue z8D_<55s?*!;U0-Ht@g!xj!G^msrx!eMM|1p!$Mk5s6kQ5c)FP?ZY>~bL%yuF2Q!C4(~?4i zt+9(J{R&~vGO^0%o!)n47!_`^-GNFs3&IeC274sx)yaf{Y2**2k*5z&qz{a)6>k0o zaQJh=VbI9mOgW1vew&gV#UbDvWisU4IY#?e?nLlOvDC)wM*qNQZFBjd&yt>QLU|@E z(ZX`3_@*&)Q8y(VV%9NE+fcLYm zUZA^L9S}*w=98wueK%5|aQIy1V2czZIZUW9R#ouj(s@qMU?QU`!sST~W?4F_#(1o0 z_EwF{i^EhgD|+PkmCBdIh{CFkV<}FPR+aR0)2MsvtHQ0k>iH#0+tJUeZK{rK6s?W* zy({-|RS2p>ie6!9ee)b30P!15-`}XKrH^>KDRZhDS*KpMyr$L}M#+IA0c$&oqIYXn zWMQS-Ub=mT(m3FI>0M1}_*jHd*MZeWkJoK{-WjYDiLTdwUbHvqjXdOloj^9cREWDZ;IHt%I3x;|enuZ{u z-Gyp1;sm;|wBtN^*ht~XBIZG%8>{2s9{ON!WpZX-9;P2oNPRi|oJ2J`_w&*Efd$sc*`AzoLi(JPVG5kF5;i~0he+QxyIGqyVKgo4AT z2+rvRFH)Ys2vKAka!U!2$lk{K^O7t>BR~&8qn44dbkzVUh6R-WU$L`hhZ!dyFR&*T z07G%~A1idbD;@ti- z34J3^Xg+|bGt?$T640^1R$E~%kQnozPpOKB67Jz*0D5p1%8v`<4FhD^z`}%c0T%&C zx#)*m)Sz~~cWK?L4(O?p%h8xLvfoIn=HNUB&X}L697!!D z$CXlUqjox0N77DhTbNVkQAr)kk(5;Y8m?rgSr(P4R+6sT4ecx0VV3n}Do0XT(YUUh zACSW}*RfWlxysp->=*=9l0NZ^dr`JjLh45AY7eGH z*MB>K6)yaSer9Nu(@Xd1`62z$#?7h!%EL*2lOb>L_SR4~;J8onts7MDHQ!A)!lv;1 z`hg578cu3M`X?vKpQd|?{G-E;kE!8v!p(op4^RqE>-}TulHNEqVIOW*8*XQu>fZn9 z-Q%>6hse?BRkOk*yRa@KtT`ea?)yvaj0|`>#+M5Xl|7!CkXrCs2F@Bd=X?wVI(S=U z{a?zxk-gx(KF~yj&`K$Fpa=w;`vvOMBfEp~k^V~q_(mF{-B*ytNqwD>yM-|d6N>Oo z3ROzC<}a}>?J~%yOPBEE-Bhr*3oP{;dD>;&b~>(O7%>Tsmx7LipD?+b4{otvefha~UFhJQ>ERbz{Y?%o!3xp;G=tBtd;gRs{hmE~rCnnnt-W%P&EjP{@v$eZ&@`5=0*W>W zy7_zm?M2?wPUR^!;LQPC`=mI-%3A}^EIE)%nwu8~Ttng0>^7)N;34>0vbydtduex` zoL%-m(HUSF9qryzIB@@4%^^k#qh#S&Qd}ZGk&SATd+2y=^qas8M_RBA^O{sGH6b-q zJ@UHW1INKUrW1%>+gtqDQ}wh6oUJ_bEG~+VGN*lTIL&s5E|eU&`U404TT0UcKq6*XUsh z$5MU<^@7g+SR~m+_w<|Ryh^zjSm4#ciWdLVYJN=~rkwGZmkV^Eb05TsyQ<#8v%A8O z!UnQ9CQBslEae19lN%>9-uKjE)_(jaW(MCE$xdRGGV29QA*Xqvd9~~%gKckN70g7^ zHNd~7aKFn;lHFiegvaP>i_6pb_9iaVL)l&~zE|B}1deafvIg!)ny`gEzc*Ej)Ml_R zb;y0b8oU9Z&r$1Ud^F2y3$WMmr>*rS{gQ`$Cm}n{&uJ3Z$Ux0^45|6q`+>@`t_M_d zHKiBuX;%PM8i4ccF1}YZ?R&-Hi6;JP;baUNtaH0co@9?d9nm74hb&FY7@ehLVQ1(L z!gf~PD#Q{G?MRA=sMJTTa+J+t0V%AmSb+{owm}~r<`fpfBEKqjKqusf>i+7mfOt@i zLN0>jb`W3W2q>&29X8SnuK)gh5VP`0Kh{FW z-jsoY`oSuq+NJTJi|fV-!Ocu1j6oGQ&9L|)*A1#t8kR~^4L>+nDo_v1T-~Kh?O|4m zK9sGV3A5VCmJ0v&1VmjbZkt9p>#)uGAL)$?&XM!X26hXHepylG@Lg!NJKf&QEMXl%b)9cF14a>$ z{JNWZ?PJmfmU#L_zCf5jLK-h5s6}d}ADk*Q@luVJ>L)-*;mD+Y*5wR zO;u6>&azi{4R27@BhRNQ{Dw`P{Uut590fLu)hp;I;E>c5pd$bt{;LE)W%jO0w_OK7 z6hE>nX&jUmM0VY*+}Tw69LCQM&PL;ZK2>2N8m}r2^@-P*Ye z&no9)_+c$LwHRi>d5fNJ*Pqz&yLcY_lrGwsXyhJc*|<9*MJh`}{LjkS->^HPw6UD; zSI%Dekba~kjSW$RM9$Rlk9f{zrHr$uE#%ihhmMOf#)__Ktvxqda-XTFP@SS_ByU&I z-o#`b$koQ|N;4zWXQQ-XKB1>`%&QP=AJ zQW-zqR}dP)7yS4ROf7o#<(}x@l9&2p;^n6t3ya2qo9@aO^!8$K0qE-pX?Tf~ua3 z0rFjSwV~9z$oZ@~^{~kQzh|%d|AejyI!xshEcNBt35 zLhyK4liyIMxx=$OUhi|^rIh+eb}5k(bhFQa`7W95vQyasV=--QQU;gN{id+O=n$K_ z#|0YHlc`?#<7<4%>Gud(p>qTGG2wIXm9m)U@fXRoTwKd00e3OM&X$XV9)>)Ii?`~Y zvc&@}$6EqGLUdBJ&pFf1Si_~(_Ufi2_P7^p(N6OLplQD{HmV~o@p{Kg%yW-b9&NrN zT@#7Quaaocl(l=TD9hu^X`Fq_{aQVgO6KY+EfEZ0j7jIqpfU?z8*kBDCYCTTP=%^t zSv_L|ro~09Vt2aEieIb1_GMZ)$#vxSX$vIEe!|vy*RoF8rlxq?o&C#;%WL$c^9IWq z_u71)YC6cin-yez8ruYv7iB|ly7I|VPi$3$*F{%x3t6&gPmKZYF0Z*bYXe@4OvQ5c zeY&`YrCT$fK3DJH0zK6j=L=^GD_b0N1D48Kzmok%3YBJvcJyTGuU6t|vaa&UQcqvc zEu5E)5KgCoeV&$!*Rs4J$NwhicYtvVPKKRRjLa^q>KY+A)an^K+seAj&+&Atvprgj9z}$q~cT@Eh=gc%CYAY!yW9idsrt zc|(*MU3r6aY7?7(gq@+l?vXi0cvYlD|EUQ-+Wfy=U<;$`cQPE4ZsTKwY z57?L~>_F4GCo*OcD>XyFnTttMT|$+3hiDplhx&Er)gY(cq=T!1f_G}!Y`Ba6 z3#BMb1WvB-JY;L)(oVEEp4uI6tZZa-0HuzN*p1w5B9j3#MFeL?Wb`t0B=u1%W$!JB z64{=}$?rau8bnn?KBx=VNr}XyU^HUeDI)(^iqXa=ATYY^@Qj@iEs05(ApIY5m4Ghyn{+fg zXlarN!&=i*G+<6Qhc zMl#nR@siwtF21DH;3zWqyD<{~yDuGye_%^dUO&%z1?#j0i$%qh0kem&(h7wEvPBba z2cHoT$gdt7B|FmF1JKkt!=DnSfL(G}sb((=M0F~2$a`AMaL{jSP%Ne1y>Fl7z=?w#_9SSof zJS%8zIW4qwkI4pjy!}goTj!h(AluG_TP$hk!satW>)f-07KcTi543ik7FxItYy_?I zyqzx+w_aelHMb#|o-d%RCsXk{H28TK;1Zr;I&G@UFT@UElu!RsWP0#Lj>m`c+IoS& zot1kq+qN&<6NQc~;d)jd<6?0TC&|vC1M9QFa|fYyki4z+$?7%Y zZMM#fyD!<(n;Z!-RRF&fKqTes z(9#iyfK)|sn^gNM&VeU-2|NUi4SSnuhmvrfuaosg*3C=yTP#42&s?$TpS--1rXdBOSKM6x4lYhT??%Mw_()3P?53rDoK%PLuh`CIgSJAXXR#1o1) za8Y>bzwqI$t?Iu>RDJc_`uV(@Swc$&4qt$b!;xKJ)jr5si+K&fE+cbAobHgv6H zdDG^o2HpZXi^B`x#xTYT9{PgGptG4$kH zq;_c}bqto+^i!4j88_?ERNd zXQ#F^m-xTE1g?r^UDN*h*c>KzMVxaCqT$I;3&xr{!5F9;D79IiV7%-=73dwp4p-aK z>p#cVZvFc&s#--hDi`YKqfj$~P2u3iz}7aiR(}_B8{GzZ z5)#Jn{jv-Fw<7PxTih6B5+Sz8!U9-|{o<|6{4zyafYlwDk!$u_4}v&;3CF<$JoXOR z8&6Az4jia;5JQApb!9fAWNQc$971kplQqKw!!`SH+&ty`tna&$V1@ zsj*9X;GJ^i!Aya{1GPxrIJ%mVMV<_RSS&P8ptTrD=GRxjyv2RA*Jz74o}@4$2z4fQ zr_$QSnTUR_;68+?u}{pkqWv6uN|?m`KH+f!?FfSf_HZYk?GQ{j#pf^#ck6=*9$8TS z8n&4Hk=(85W2FO|9qHBx*bG_+PJ|ywI!TgZ*hQhiKnuWiN{V|Hbv}qAYe*TKc90@| zlM&F?8n?Vcp+Z0g-V5R;maH17RX5WBMc-o(6vr<6VIl-YwjpqK9DI&-3tvUy>y zADTNVB^aaK2C4oD38to-vtYJ3*KBZ`U{B7XcK?b_QpmLnu?1wS}esn5(F z#cckVdR}XrKb)YDpj!P}9VM~wt&TZ{p9gx4tDo4~~b+KXTqG_5OLv>}fNR<2W_ za+o4*chPE`M~RrP5eWlY#s}GFJgSgNyTX&7iL;qLJOul)=?y1fpUn4TDMy-ScRTxJ z-Vl-#6kY7DF3cBg{>$6#GHbV63_cGJgD_!$jZkn7A5U+H?8ah9I4W~K9=9M`jQ-Ck z_nhpDl0VUehmV(X=i$bGAhoMhZA`~hS->szewAG$6;;pi?njh=i}H(1Vt!5sM8{`F za7;Nm*bJ$m$$>?o)xUQAaN7hu%JRZc`au+cV5qdJShwDQUwkGPNdv|w-F%6SewKk_*ycnvL? zvps$Z$M^V^^lpO{P|br@L#(pF+n7>uO0%}}q$~GIYl0VD#>dZAdq>_O5XHOT(?%as zp{uycsE+jSmAgG*j22X2p*|F1% zMuy0j-38$Qss<7_}4<#dwe9w`e3w=b(8WH{U z6BZ&C2GWciVT6uA7O^DON=8bO*8|>6D!`;&s+)9jsh%bswj_FR(OtM&UxcGr*A3U> z#U&yF&a;dzF4>@rUtF?GPQUCVmT4|7d2=(dXuXNUgQn$PhGtu}x#kz_x?7MUw(R2Bf{9ubXbh5(>I-;Sibd`0vvj|x+R?|ey`6FBRV z_u1}%NlG?E0{;{&MQqI|(ijXg=!+>~`T@mEkz1ED8ZQh@a$$?8S-n<)f&823x@Z}; zESQ=wOWlSmo9-B%e4DTa^)X@q2ngARlQ*#v*Qw`b%+15Mj6k0{Z8!cTW&jAS_x1w| zifZV9e$biz!#Rr$(RV_p4S=BFxbSHPqbu0>k^ZWgWI{H`9w7mxK>M!F89>O+CJO2# z+xvqST+z6NI$=KAiX=LA2@%?t^u$=1S_2eM00%YiqktQxQI0?OO^rX=DvE|lO(Lid zHT?z0?YK*V9)!bT1|O~cB)kRtI&~YRM<-vT-4^{&xi-t?Mrcke$JY3dV@*>34Ob9g z>bRIxIPpXGX2^d+jqyI%7w#T^XO54Lzu(!suvOjQ8eJVJ&)^l@6#Z551xD(~=4*X} zR_emM-b6VfGcia=4?7NbV&dWBD9Nl`Y_ny(&Ko0zk<*3H*D?AdZkC7pz|;$vMp2;#Nqk(<8$Ms2~|*h(Cb}&5VQ-kZxQRjutryl?*M4l@oLp z*5?z%!+@|KP*mc0(9$@^lbH5MqADQ3jV2I`yI=z2ZU^B`Y>08yzHsxAdo$L|T9z0F z9_D=<1D|e?jC3&Y$?^9mniruBvcu2@{m1)Sf={CEGo#I8{{zwH#MISfoUys!c_Ywo zm8an*nnhES0no5;o|2~jbOLaMJ%2XBp3$vrsW{k!FkJbwG3+TMQHz1JH)tmz5RBm2 z5omlC!R6;Ni+6%IUsmF81bftR$B6&Wre+Zql2om;rv8r=ZcszkkJEmFGi(UBV*8cA zvL7N~n|vEhR8-lS5@<;>O-E4p5m_Va*UMlu8PqSSlGLalU~aacBz8u>Y7E{sQ@0lS zI8boPDC57bOzy5nu==G5+r{7~oq5y&|fmtK#NlKw~6FOrQUx@5=r#ZE`7BiB;C(6WRrvN=k6;a0O10OtY? zwC@9getzsgwM-@~g{4U0os<}r@ibF8jJr6e!XH(Y$e@YdH&w|J1_~;{@i$cxc^DKR z9>$M&7)(!fu#vBm_)~RUfI>+fyN29y0G}F7>!H85o3M6OT2ks;yrSx*l|Nkd!9#S(3x1Pr&&nTwS#W#a7k!C zE#6F#-!WLwvLSb+W2dPm!Z=RrNdY>~`B<)tx`x|m>d|bqo(E;wvfsx!_MO#vgWEV@ z&)9|ol93SGN!>1GceA<0!^pQMUs->isf!@Lbd=N2;oX{7gOwjb-94t8KjfLbU5LDS z@Ha)Z9keAgzU4e$lx>xAvh1+~)l{Di|fW{6vV>J`@4@~x(8mEp?WVjRoZQAAdpJJ(%@=G^0CO$FC@kzwvsgPQHQk(Wozs4G5 zyZ4y|3R{4}7C|-*q}rnHcf&T#>=yNDCS_n|n?%j*7R_wIPcySysx5J5tz=L6HM9I^ zW+@+M)&`HWxA{Dl&CJ^1ZDz+u?uwyzKF2^g`iIAYfZHmIJVRS4hq}Z>m!-BDmR)B{ zX) zAOpJSpVD8UDy8xAn-({o^2)kjFZhv^1v@dqN(HOP3@y>wf<_6_t;bn!bPv~-P`xU( zvr1%Wc?Q0`e8~1#-;TKysWL-Ps{|a-2DFv;#+TQPbhl@Z1C4DS!>?&p2T>T^UF>@3 z_fGs|^?Q4+p)VK5a!%IRp(Pe^(AEh4DJp;lgL+BG3m6fr>2M6AJHMA9F7dEs+~V@= zg^49KAEfh9NEZ_H#|jauRRoMsOc*XrapA-CPA>rjLxT>7&2@)(|F>U=+jJd@=7bE=7T1sbB6hp zr-W`3nx4;200n(cWukBE*bjFWg&+FF2{ehpKNLEtxbbXjTD{7N*)}w~E!R{p7q{l) z^Gr+3H54GBkf1%o1Owt8Q_d!jE_iE)TXa}fror1|Yzy+^_LeRXQWlOlD#I<3th{o# zhrfa)jLab-`MP;S0#5V_P#iwncl_)*L_-@{#&xrE*vlS+O89v2K?aXS6HFO`Y;)2@G_N z?sdm&&Sf@p!`fR%hj_}3S;qz?3$d%Aj#a(n~wJe((;7kHmT#?<6j$a~iK7WaA^^cMUEi zXFGw1H4igqWI=72HKQT>VPY7{qu*9bT?lC~C18q#}|1%}CXoRC(MQxzPyE5^)q zWQJ`E2}NCe-$5wGt67ss?2L;<9VgXwk|U95U!*KhZtp5w9Fa(dZ=*vN2#gKIy>(9_ zF}E9?NsHoeBqLPdm313`CGj*l8G@rTCOtWID~T~PFA zWT%Bi;QPyQP=OWs!Ot158-6L*%UVZII}(Sf5)+1ON>ENx5P=jM5{KwX{4o-^0aIjL zpW-G|B6s9PEJFy{eGP|$?Np{ORyxLHdg=V-s2C%)OL(as8O8TCt{iYN)WIrbT@%#Q zCl@HhXp=yhL72>#oNt7Qg1MV8Q4eCz5hQ7JCP*;NP&`QxgG4F>nR1wNl;0!>Xia{J z4#@4y&|tDg@URJMfG}gLu@Ml)@-b=PYXn_2GwkZ%-Nqo1X$tgB;~|)~`j&XE6@$Bw zX~aP-fF10$I4qofS@t&Vnf;KtaqEbxYFI9A7N_I)h|TOp*h8ycn0a zMN?0hJTC;(eC_7!{zaSzF0u^o08sPgtLk@{;n0b2PU{c@cL!U?yNLsRlsOWk{P$87xA39pn_ZhVWA2yZ)|8|`KliLlF7FJ4oC zMlla7CMULe9oJx2-1=@u6afIU{DL^k2u1=81EnbHx%Ix9jmnCePzP5sdL;!x7e&); zgbrXnWlJ|!R7y}WDt^-Rmu`4euL6G5d<^cdMK$b(CsG?c>rztPd_wDyW7%{+MyHN}LJX11HAx4RTvMc-2b%?G*Dgi1CdW%Z zMCqe;e@s`#wMJoNc)Yr;%xK^7VdO{~fl{8jt?Z@^?52k|Z0+$?P#R!FQRxGUo-v>iuv^7Xu(JhP< zO0t6y;%R9DO~1rb_tn{l1f~ybvZI386;eDZAi}6miU&q$O~6`cfMcHkrW{=3>-p$( zt*LX^An%xoH66x4bFlBm-3uVO6u6z6aqp-lBbs-Ru=`+y+!?_})wZdWfmJ^iR8m(Mpgq7w$Zh^5cW`Sun78o*o zoBX<^xNtmGQbGv!fcc6!z#yv2kEIAVifJamMP`7OtH z-BbRv)=F=1UaZ+ZE6A6dQnAXmq@JOevCgC9VOtKh8jDk`ZLCA;Y^?NC?5I!omuYM& z*EKn@@>#EZ$Poq~{8V?x8bEbT4Y0si*8sMatZ%5v(kbCdTs9f@v62BRhC^25zU;2g zO*RdxUqIJs-2fRyNRyHRSf1K-N^P&o~c`?mkADbs5@T>ZBIkRIMx3&NWCl#lS zOOJGf%zCBl%4mkLSc#)qvz20mGKFGe@YXFuhFOLcGWj%^b*|RK4kTHr*TxX)TzmIr z^tom^Yaqz#-9RHmn_GyFH5gQsSYx0d`?%56+qFtUWHU526<)@+llYHyhU3dxmp?9{ z-PX3rWRuYoW?N0@Edf_9HT0AJyyFo&`IK z-&9;JT>E0{!K#0?`eU{8cVx4~tH*mNo8{T|h=re(yOoh0;fR1>1pmU+Z?#Y*w$F>p zYn5W-kuUQPK*wU-YQ{#ooc(|uyfiS(Xp2IXme*dKeJ4*gbYl*nM8XnO6`I1TX>$&W z8>(Z~RCK4r$!tDzJ|Hmq_{$qog@^-94K|_FU=vCWbjw)vR#~l7NPV| z)s$IWf>y;r^Q*<82_YpGZEQ$|Y&XgancILDVs)wkYFH5reJmjArI~uv6!$Y=hsDCu zGW(*LdFj+ub=;HU`Ma?-^795~zE^{EY*bkLY_cjyUSC}ijH5IcQf6*I;3;iJneaBd z#u7_whQ_9ohBe@a?rVpNu4{+N7S)^{ruSx79NUJPXqoK*wakQ#Z%9pKX*#DttGAhz z!T5#gzA9gHz_u_-=RpF$gpBAC@JD$g@aqv;TQ08NXzwW*25c9~JacRp3b12kYefSv zsQxt_=&L~odWI|hHr9cjab50fI*@76&U`iyxKZi+nhuoLQ##Ny?$BeJsdOMvjWdH; z^*^f)^a<%e+W+{P4y1kCf0Q~<#DTBrKyti$&N`5};%H;!e+C^$p0YXzq{a2v#*aLR z^_i6;S9R`1^X$kQYEfak7o#F3MOOEJ^5=nO^J%eK++AEvAaCM!@$_xld|H$@(SU5M zeB>+66US#;?Cq-hYvs>h4jEB^{$zm9{sHJA8DD*U4(B<6et7RgKkBvh019T0krG zQ`MrZGKM7}Y3mBO8F1?JbvNNs<0!RMov&@XC39a;xkoeRz+BcH{ zxRqr6A+K<9$}5~3^+ow4$O=ViUX?diTtcZ zLD~@yo5GHxG%P%!v~Ezad6$E#kadP_c1KouRBW|x=1DWKP(^r2%!$Hn1s)L?KLXjv z^mPh>d!j8fm~a>_ZtwRDmxQwT%&8;Td4wS#YtML$4G`yW@L7ffvAdr8HOTwlZ3(m& zv8t&=AINxy2IWCuV;$$76Kqr5G<1wfD;%77sICz+j%(+g+^LOu8&umP@a^!>_7U)P z<_Wu%G34zL_{PEQn#YOrLpnC44nY9(E}6TM%=41W^J9{Ep1I)zlDY0h$B_AIKFVf$ zGTF=(tdh+-*To;MQT}-jd8uA5$q+xT)i$P>ER8tcCa}%Zmnd<}RKPQ)Se4=j#+=eKiEe&8!jYPH z53!9?z<(3!`M5ZqmpC@a02dd>4i6W{+k|!IO0vzxvG-8jcr+8Y7)qiNxPnki%^_(GlTD6b!6!OYhWqI$mS#s3k?N(-2?4 zSMW$v5w?10`JReu{maLeNrM8^Fmw*NI`=UJv5BEZi$DykyZ&6g{tKcttP#VC@!E|# zBRtV@NWM0BB6uYvF>ndJ1TMz=y;ZL9em8HpO5vZC3!_sAG@Y{_e5}AK%O#;0Sh+CW z%z*A1WRU-E&F58BR-LEVpjm~`BB)vgVJZ-h0U~n|X5mcaJEV!2{--(KvoJRp$pF0$=%r`U%D|8~nlDSf48Uq@XWvtcMDgt59@u zd{fW@$kvKjj2g?CRb&FpIv251j2FlL6#RioQ+Onc^f1SVFUO(x6j3dgwR|e1T1CV* zJHgCvW>DV2Uv)$t!2Qc~-$M#~rM$git{?2p=|JstEGBTM2S)MJ;ztNX{M%p1o4{Vs zc)_Il#AY5Rrh$X0M!Kgt9pq1e!eH^D&nDgtuL*WdnFPD3GNXV2=*89@u^{49LM9q( z!IU#p#d2j}{IAv@X46QWJOl%q(YusGf6{hG|C2G607q;!rnqrDO(`3_TSI}vk6Yp4 z&7HgR3yXtIo40I*kcx1>2UiQVtWZVx>-c)^+!npw_+$6N43@(#?FAO$9r1PN+$O#L zW_&$g`=&+sP<(yyoW*f_CcZ9GzxJvw*7jKuJ{n(N;+Mz0?Z-X!6@I(hZ#S=y zYY{#jU%y^kW?Tw<)H5%MM2qlS@pVz>KZ@`N@pVo%*dlx|zV6g+NfAEPys|S=gq#13 zSM|rH!W7}d@%<7Bxgxy%|MlcoN(V0lPSo{frpO|W_J`7^K@ZzcEbvBEKqs;(Fmi(} zCk&*D9Z*213x@NE^D9JZz?PsY3)|hS0X* zoGSwRhzG+@5Qc02YYxm8#O77E2$C5)f>#Fd47X{4(Es%!@7xfG_FF)4YQiE#w(1sF z*y{tn2?;;Ty#A+YLfD08hdO&`H% zVahRy+NJ=$)>|Vf!%7t!OQAF|^6@hm?+XW;ZTQ{M@Hc1^A8Z1OO+$L!huAAk;TAxp zV0FeF`ozs^#|demr8zX$C$bsX+9R+vKx-S&IuU5CR@Peg-}t8zOctI^01Vo18j9{b zF^e?!DX`&Lfb!?v-T=9NfVuZshtUbK*bF4D{!Vl!8$%cHT9hT{Yz&QMtW;$k?Z$-} zJX7abASbp)&w2Oxs!7dWw-=^$I#rp2rI8gOlZc+2N>RAQ`>;k;EdoTW1*|5v9v{J+Ql z<=z%W80}jh)LN|-DO5cRi=|r}rT%BUH>v>FSy+&3p^JE+EJ19Di|#=f(K;U`wE5Wz zqRoOOu&)Zx(PnN3T&Nbqh_^ZUm-VwBO))nSA>v6m2(#!tmZ-v;%@2aiUOvwa3qxhP zmpfTsJY)Y2PWxX>7ss-4s+6)^(Ry{hIQHMf%h>k~A3bwHS{c(@{I(Z6eaLEoF>hkb zJSvn(RcdKeDAElVgd%=Cyp0xO^2Fez7Irjj3czWhDup-_r>8AwX(H~@iuFg%9o5rPJsq!S5bLq?XJ=oJpE6TDJ+Ege){|QYY+Ps4 zAB(tP{h?pjPY*(Qa|aJ_$Oo3h-7p6jC8wo18Ep+*K$SI=XW5E2_w_ZJZt%ZS7n=c%ekv3oX{KB{!mhS;8+$G^PXkA z44rtCX6FuZ1j!1P#!D(9z{h68Gyg%D0P!gPz(R$?5=uzukPn>|ObAcj0*ACKZfH)8 z=cL*6`jGAxe-AxALU#o1&^Vv@RlBc&wIYjm`$Wo`mQ$8I3!oV08j*m=a=Zj2YxjXg z2{4OPCKY*Xcw2aD3j%3)K3+zaJ~)gv9}3<591GKEBYni^{mwz~t&;ywC7| z05%K3;VXuGK!oV{lUTE{@j^_{W=ak6$WIITg0_}(d|q}F3-+(Os?Z~Buu=(?O)F=n zNLC*18X`OxI)l@*1@vYG_wp=Tscu?fJ7ulSB(x2MG zqEuFya%OGeYnDD+e3^ODn!8}%SkP-CL4`+wn=B_RQ9vVGHPENe&h>P6GM zLxZ+alTP34>AQYM?lJR{;X!LnSz!S6(m1|K{W|hf!ctjOo-)kcDnLOJtZj{;v?xYt zQ^B}e1|wDQXjAb0d|777i*Nyu!{W-*g*<6VT|iS>RX3IT+B>e8zkz->Dq~oK3wXe5 z*eh(Z=do(Dm9-d%Qnb+jSYEUm-P^Y^&)LWPF^$^mf*ebp^rMh{#melzx+Cm?IqqaN zgn3+FzN@tt9JQ@#RxqrZDcReHCcQGdR(G2cAlJ%c97^ZRrWP|W0@lqq5F^xu7^dv^ z>bCJk1^(!WDGFnxrSZ%5Ae==^1x>DF*Q_*%Ms8sl$+9i6I9q$WvE4iQF}C}M^QxPk2JlE+d>&a9(J1y7KP$M6zKw3~g_J8T1+ii8M{ahA%OELotwg!b z0HY>Y#?mr&!{&nsy;IqKl_{Gto~N}>ahPnCRO}u9M}@uBg`HTzy6w)ii9zqVX?ke? zv|5@}B|eBGxj#V#YM=Mek^}G(Tc6DVG>$+fZn>E^VtSxLNg(p zmRMgFV0_xUnc8t?^K32c*?>Vkk1}Bo*T0lukxL#~5k-5|nP!5_rw9qrI%JYy9glpL zE{L1$vz|v{VN!6{VAT?5WvwNirz3AkH7E2IZ)p{xtLw^fRi0Z*H8JBQxT}#oDD$St zuPf11m|9?~S^Rgriuu%xt(oRRp~G5eutp0}N+IeRDHY|0nU72fHW9_)50rM39RyM` zWAU?MkTI-Aw$Y&2qf4KGwoWdOx>OXIMO>id70ZdHI{>7qLdy)5rz)v<;gf&;Yk%26 z#P?A$HGRmj!Chtl+s{(J`miA@nav3A%AQPQcFEO9V$x#&>a$k+K6mz&zOzWN^YLA3 z`3^XmgTd9sd3z+zqw=s17ch`6aQbYbhv@!k{77|9ZB*E?K6D-5c;YrCbYB^=RI3F9DYWses-AADdf--7T4^p~3Gny1_wCl7e;$3?c;$Jb zscK!{CX{aAo{et#va4D~_kf{1ue;F{gwq!1c}8r)HfA9UcfCtJZ}zlw4QZ<=2$+$^0Ep@;SL!hSQ2fzcFu$?~{0)cRG z42}mJ9TRIA3bD(BXs^Ro2_&?R(j9RLky4fFC<~X>q$O+REWP(L6~ zcsd=aTdZKro-4$TtGVeG!Uy9J1r7~tG}s2!v5pvd;G3k}866tYA2X^hKbQtMQK8^# zu%>5;6yw!7lrhSq@!iwWmIN*T;YRkm#UN zj$irwr*8YVH~y!?-|HEk`uy*G;l`W({gGEHL!aPhAGlY5dQE=__e!{EHX{LFDKd-5 zeANHb!d)B~814XuZo>=&HcLuCwS!m+QO+DAz#=M5j|GkC7NV&n`4^ayd`!2{+nAY9 zx`oC$R$|fK#_}{(q&l_zlS}(ZrbJ@bOG6R(Y7iP4)}90l>%klCqd>`96!QXswijT= zZqy%Z+^bHOT+>Pzm{l38H`Rplz-iy8@>r$0Q~DjVn&?t&TC*s@lMmTs+wKey3D|v0 z?K(Zd_hhJpNCuCT?Bt*y7Mjv*@Lp5)qVGZNWJyDHTWeNKSDJAQdJGJZhsUVQ{*WbH zPc`MCAJ`9(N!wG07&$&p5&?tv>-@K%q9!R@>4dEW4b_;SSK@;}TG8TT3D+P)jbD zF|&&H|Brm`hVT&BD?kF{@Bq&iq8yB%329%ZaJeo9LV!-Xo?DTxp?xsN%$PSLx56{$ z(-;9U&%e^H;qLW+rEB;*I0?6daltS~T=J`tM;6TS6qigJ!e3FGvNhtAFt^h)N)Up1 z5x!3{O1wzKVNcH$Q$gd38}U?$)WfdJTnS6!xWM3natOuxLlJPM*OxNDiR=*~<0=&t zl?_xXC)7(Bo;V6ay@w&?pcPkj7+DSofjRU5QvmB(VSf z46={b_CvyGMXN)0EWCESRg4O=KyjbDt(8rVj! z-+xx-5txrpV`0;1dl;i>%mHO_#mUmoYX( z<&aHMaqMn|cvE~`pP=H2BvKO8&MQ!E#krsl*t+alTSW^#L#tx^H25s7 zMo}R1noAbr|D|IP&Mqb>Myc=}FGw3n-h(MKuTC zeR6p;00Mw8TjQ&YJW9M^Ldr_&x`>q~awJvp8fxfWabUhB_ogIv2mht4 z<`f*znrY;ConOhy+-hROJimgK3sI-MvQdqA6jSBpuCZ3LEN2_(KPLaRpou+_YBbfh z+>z60@Jkxg9%d%BhnbDE2l6m#d|O;Osux$oIjBOKeT+U#8S09bwVEN9A=S*j%XilE zqQ3?Fjuyp2$?7ttTqm6!A`G;rI#HceC)$OS@meg=>Lmsg3VKzK?_5nsjZ} zn|he)Z>Rdf3~v!p2zh*nIw_85LeT@4ypxOvz3Qg*|QCB~-!i%ecWQ9asceYbg~~2U*T}*lPaL`5FCG zcnon&9vFY9#H>MXU%=}N6b%-SvCwIX9%I*MqG$`rMI$2R8DGIuz1X#|6x=uIrxAc_ zytlwJb=l?vfJqYu@T1uoGG4)QRpHNVn8*ZYOpJiJ6E@&IzYlA0LcGdUfX3KyskE$U zRbmy|Er6IfC~kuzI}!{h*^!`=BrApNOr=JH9M&+_TWZ?yx+o-B(sGcVZnZTZx)jH{ zWOq^;W+es%Q*w>AOIyC==m>{Pz~m?>{m;xdRzn(@G&HJ?+Av(n%j)X~wa&IGdM<_p z?1Y$fN!49}bnzM>lE$_+THOes;`NjDF$!@V!#inz;}h2m$k;_(HZUWZX0V~zS|~SU zt61z2G{y5qIBd%?BP}RxlC;=uiWHSdi)Dm?RegjNZ$w&hw=)53lssX-8iTh67=a!0 zyA@3N1v7_?eFG4gG{gv4OcX?r=M%&urCduPK0rLFLUOcDFBPTNo`qDT_u|C-D9D{5 zA84YFvD=7&Xk`!-&&($thhvz&r>v*+BGp+h`fXC4(#sPuMZZn9wLj(M$(W+wCfgCE zJRMW?+hjYcl*9Z{JNj+1-Kv+HV~T#8Y{&F+OH9#klkHBu+!j;x+hn_aJmt7v^hJ%{ zHU4t9Ui3vN?-_qNp%;Bo%01&R_v=Mplycwr%Y%B+7o|Kf{_==k^hGHTjlVpq7kyF6 z$?=!R^`b9IIi;7!;){Npl&AFaL`>0dlWh&O4Nt}t{WjT-DCOyxqTeRlQKcN_j~dl) zlkHZ$+#FN%+hjYYms?_rew%D}>gBeWqTeRlalPCgQ}o+pyIU`J#T5NE*-q%?JuyYU zO}6{>a!*XrZCF# zGkw9iov9M04WLS7s1o9QVr5?fekYrYGgVhATbOjdSm`0Zd+h*KW&g9XxhFj$O58;BDq#Mg|$#*J1cc@xd?v(yO z4F&oG$-X^>v>ZHSN?iK+9ox&%{=yLXH*sUdlZC0VuX;H*UdaNhWAWNgPBXFuVhER*VOJ{ZgN0d?d;elqt6X3rK6 z7~B5DPsA59f+^xdtCv&%)`(rgH^`S*>m1@Qm_k~Zn+P9n{pI9J&$%>tj{KoE4!mZ1 zQS43s!u|9ISjZanOqV76;5S*`q8i=p-&r~6$xM6LehA$@kso8=eN9F^g@@kiyy!&y zTm(H?_q0i({SEgQv2WOQ!b$pSax&bl5)8CeB)ld$0te%FQii` z>6t<3i%RLw4f>SBh(k}3%2=MviV9I?Ck4~L;Q^`zoKna?iFOApY1E! zG3yE0p?kVfS_za;e!~HK!kb7(RdO}hYFtWa84n}$;^bKZ4;Y0|pfSR!ST!t{*oLv1 zKvw2JSV#TVDaWO^<7Cu$mkUpA_z>Cn@L`mU2s^Y@Wy5FBjgJF{FXx9{aroMM*6`&5 zuHk!28b0Bw=rT(+lI$y-#)d!MF^85-P5*T`4~#~v?)X-Zcx&TQV*`(F^K{aP%FniB z;l#vv`&&elQ{O(HyN3cK+J>BkWeL?-?aHIis0(NB?6siVEvVa&dweoqI`fA}P7z)L z3ke-rLXfz|NX=LXC8Xk$|O=rev@wlW~aa zKAGV;qej3?12Bz9R2=9dQ>q&-Om}qj-FhF)g|7ukW&G3meb&+Bf$`?6`}>Q6QI0Nb zT>3zN)*q^De}8ip&Q;2TZWb-u?@ekFDv`B+rc{o9h;NeZ8f@7;@oGBlJ|2*W*fHjjYSl zwR-mT{dd)V!Or-*+CNv0k+9Q2t!>(z8F2G@KaP(BUHeCmhYSXq46SMR^&b;z>6z6Y ztU5XOFu!vDG4`@GeE#=AIFD{aMr>7^N?VC*n&trlr-5Lq8WJlH`W9~b0}6;`JWk2M z7s~K&^nslG!OUN5ugv-Os1tezbM{ zm%_(~Lo!Y6vCc2X$>+#ju!(6WpVtamtsS-?KtOA;E*npyLSDzyy#OQpkPaoy&j|bD z4iFfEdJnuvh=N3Cx_81+vi@GzePEVo9YzgP!vDc{OTq|MkJ?id{*UltM*)AV%)3!< zX^rbG#a^~$ z0wDbwUIv$Q;U>TN!J&Ldq_O0Psn}=FJd$PPlS8OnCuElZWSp^*%oy;4V32c^yox16 ze9B77bAmMx{{{Q3oKK@uBEjue3G^si{$~2-q5aUZzC3)=JOQOH!685k1 zMwu1W!Zc{K7Q5C6d9wf%XK**B%M$*_@7A<)0#w!zos@I0V?~M5TpBB;2PvRTbUcQ+ z&_(lsd@6cmjhr;$c&hn{RI_QqYSM|SQG#Bf^UlU z335lP+~#vMMMxA)5sIYdlU0$0SflyKi}fR^0t8SZ6W~46*^f?umC}~ix~}n}DgFsx z^r+tp$lx-;P80$p_$VZnLt+I`lPq>M8qA={aO_tFZ6=juX`doDq`!Is-Ab$F!`);u zlKa0Hd&8I`1JI963pmffZUyOVQ`EW$ko8#%Djb8;4Bn1JzkVb|pVY(q{LR{Vi08piP1Lr)DCp&maxd-*S^sw> zXB;rnQLU#sa{S1z3mC$=!^icc-s6)A?g;8zedK_WIafQ}YS^%O;> z(ypQPoB^octakqyODdA9PPSHkhgb)YApop9 zCeLN@X+=jaX}xTk@1xnU7s-n9DP_#eQ#(aJq?UMQ*i|*TrlvLQi3EckNn>UPKOXO! zGoKLZ6NuL<5hY}5AxDaU2Eho2_NClwO>|h}stfPE;eVCD%&kB1r5JxHn-@B+nS)Do zqE6wc(!ur6YHgFP$MU6-P^PQcNxL)4}2 z>4}}6Qq@9eQQ*R3S+&S)g-je~>V+DVzENfD(qWhwY|7=7ikh<6*Y-8gCJ8VqQL7ME zJf%UWxPkKEicQsyrm4wltO2I$aycNYRjVrY$16N-LSL$@vvy-kP?xKfbXwf6jI3RU z+xdXEt2oLMKMGyyEUYm8^CFD^u)&?QguM+FR)h*%j>N~o-If@Z_&aE=lcl2_9npd3b#o6u`jUEQD3CEz`bT=mma9&PF^`{EU3r;N3Tqa7u;l) z)JTzM7Tcy(?A1T(IN#|H%&LIx5_;-jg|09Mn+{K!hdGaiKKNqg#^2;(ia7Ztf) zCJ|*N7ehJuc>d~KzC{}(J!VOu!unDtEeR**^+|VIl019Xwe@JGw&33dj0RpJtX-Gs zKFb7ll8Jp-NPK;sKe9X{4^HyxIG7A3p??roKLoRfI#yKf73cz65ui2d2KZkb40mC3 zmQWyb4T)R^N_DT;S)<|V3|QN(D_sl0_lyYw!%N15g0Tvj@N-36dc+hYvGgBoRC0D@ zOM$aXqh_`pLXRO$Cl?-W)3@`*U0PunPTh}gU_tEK;dts5+0kOP@F1or8uKbVajes9 zld`qpVh3i5W9j$rb5=;_x->xl3VyCs$PJN>k$DSBV+T$?pe#_r@jnCv$V*)l!+9+o zDgcNaGZSwW2s8otelhM2b%iyV?$uG2IX2XsAfWR?PXZGI_GdEQbm)tj?1KYy6VcPw3gK;N(5AAbJS?4>-t z^XK@yz*mcff6e~z==)~1=#xGY9{6pPz6-gYI*1_zg!L1kPRW<>IQf9Kp=UDZk0LZ0{iyp^0j_uR9e^FROd-_E)5Ipcxk zMZC2%kgOo2G@ENeVU`j}>!qWPPwc<(z_r&vfJZDfKKVkH#nR26FEX5lhecJ$#=aM$ z;fV?85%W-62YJRnnmhF$NaK&lu+=D_Nz_6JdtQ|Tvf%VksMnzo$Y~5r^*AM}f(ti~ z`dSxp`Qj496E$V#W-j|8z-IA7qI-md<2B&o>QEHG0|+B=7XO_$@TFn_VkG`S@|)u! zNTJ{%;c2RcYRZH=()R1tNMy{(f{0`@Mh)Xv9uVxzQiQh^Cc#uRf#IS(%&4B1un4&Ifq;%c3X3Yz278WbSZmfyg z89Agq(VrYmlg*-1l?9n_QI;U#LkMOI^T=Kc!4$s#fLC$AUO*|1A4*Bm7GI|1g|Qy; zAxLzx(FCdWOe&}2EvOI{)Tlf|&KQhfWb|a9$f~!5Ls4sYv6`(E;{(@dyTBz}S|I{6 zN_U~m5Fc75!fI;?%#8m`64IaW$E%nhN5+N6fEzxoK*TB`{bipjXl}t{Ci{KLJ|#lu zNmvclut#+<&5OBp+a!Nn$%#L*f(5$Xlx>l_2JzZ<#vdZ75r~-2fMKD)UKowfM@qvT zBYMZZhNsIHs7FO#cj-OkuB>QyTJCr~&PtvtJCXD#GeUckHHoK#oj9PuG1d;Y6ZVA! zYka!MZ@*ITEtdEbwwpY+*-@!8v>C01{qSP?Y(dm~sK#T;81iO^xsp)Gr-SXh&X%v7|tBhVRcNB9?d6js-~C2&C63Ct-sCD`oLdx3o~Wyc{ecs6xz9&Iw%MR|PCSuTl%hW;pNq3g|Mp zw>RB>&tpz54!SPi#jVK}ZM&3bg)Z2&

-jmBr*9Rhh%-kZ&NlP@O0ozb@hEO1%x& z8PeKH>g|#?DMfDUf<>E;OL~v!9t(^X6uPJ4=@#^-CJY3Ee1j0ENQ30sL17>$h}}n* zuG^Zag(Td)DY0yf_n4d4!+3-wDyXKNG@&Z~BY_hKHG(BCdMio~X9xM)*g*y5USF|J|c%(efb z{K7u2G4BknF$Q$(;}SP@;Zd5wH9Rf1xP}oHu2E*G-1)2&PhbU)~zX#294D=Gd>}CtAMx&eOFbztBl>j z5ESBtB#DBinW=r*={z6;!bj z-1c2(;u!Jeiht<9*~f~nRQ$x>{;-iIJmHKTSwXc)@U2hYdB(9)OfxC&y#23lSx6Fd z`S?*v;;S4qao_cK19$OfKFgRdh~F+5{2wGurn|yJ!EmWP8Y+BpFb?z}J+*CShyeLr zO!E^?8kYAc)pAR$;u)dzF`EVel67R4^usC?LXj+`L#>7Hs3o_4*D-9d6-sHffQ)tP zu3rmDsBFYs!>?=FZOcjvGk~F5bZM<>woNNdq#DB}qCOJ;S5s*i5Q8$%V8I!gN+YHM z{XIr0G|=7$Z`fCxGc4Vjd0Sc~z$>*l)RwA%dNm1~tOmnGRUL@9k$s+n`6HT3(Nubp zecf#&cTNY`GeN6e(#TebN9F3@U&xJbCErnk4(OLmw7!kId|aG5{fh5I>hfXpGIS|TN3uJ)1m!s z_g_~JYF-jveI3TWQG(1Fr-W=q1V~H5Tdwm$yq`?oyXqh?5$z4#Or@(19?MOgoemPMsmuSsy9XN-s3JQz~V5JEBtX zoT;ghcbl#5mwt7wt>z$a`<61gY?3~PoEhHxwj6sdH?3z}hhyjSA#37NREPWBH)}#w^&=ROINnB(Xa@{qMt$rS;ImvX10f{YhT+=r5 zGE{gO@?VOO525*B1UPq#Y({jgS0>}dheRQl;ccGJw!)Y|BqEWmlPyOi{w#{Jm}o+9 zx)zhvZ=pP&+0qNosdFic6)0**qS|g9b$_zo8_UwTek*j7 zq2GQgVAo?bk+B-S4B?~gWKkkDgYDO(VlkJ)SJ*VpWI=EiAW++^1<1&b)+!CJy@5vC zt!6^J2~t)7F&KU~Fp&u{?t&x)DQ*Bmq%DF=4m1@&QNObQGL>qB9f)qiQiZZha z#S;`rN)>4Una$h+a=5D72}v6fic6u&x$ih*V}U>_GQ|3Dk+2(%u{@!b>~WSMs+vnZ zfe@sWyte$X*0mwJ4GyhRvt$)tt823hA@7=aba&Mk+yWAgiO4u=v30Ot)^H#Bqzw0C zR%8%^Ofe0E(UN&SAH2pmA50(}i*uerfq}lO$v4!#X^Lg1R9j%6&vTK1zKQV-^e1Da zVv7a4$JZuX&W%aOZaK`XjvN3BYB@_!2#@oG#Vw~pkkNb_#&n{pq!WZ*@lNy49Eyg&s1tOvny=yf9b$YP z*+vJ)Cd}CT$0jDn-e4`w*HLF>S}-f^fRoXc#_zXM9A9PX%c-<0FdgFLLq%WL{AF2a zTH&acWyot-9IFK}GwZA4^{f&D(Dl>da_gsQeXx4`bzT=@U7OE3IUtBSDYk`ES@x3m zkc^vCSc~;v(1z87HN?2<@_El~T`^-!16%iU(dqsT-!{fuo6__=!tPPJqT4S-u zZCDs60ym%plhGJ1q9`5nL}M<_S+`hho>kL&86ZwIgD9 z%$+840URR-v|C9)oR_@H7uOpOgk>GZC!-Tc-QKXXrlg8E~hx zi^hV*Cb*!`j5_9*uCBA7;q&V0;c{pGW+Nt(DMt_JpekOuxkiO@?PZljMrLnh_Qbsz zf&`hwOy)9-COXXbZJ`c5&AqlA;4xll%a$gy5=Ex1gJy~rj`1-88IpuNgmV-@8VCYp zqo5(L3LSy1muaOo>fj>2@?r9b^R84z0IRhk@!qT)ET86jvhQLCn;IclK&=eekum}n$e)|!zC#>kKM zht?|Y0%Oq|j2~-&VPkvJG|^L!Y2c6w^Z-B+E>gdV@iS0j%R+pimByX}pDCppGF)~( z5epUm-cAt^kI+m)k2FH*jXhC7k(va|o1cK|m6QM>LrH@0)C9DuB!S2>TZJhh7LW3R zKFMAQ&_E;&w$pIf^^LN|U*83KMdo>e2WXMW!PUBmasAR_fh9bv1pPoo{QE`EI?Az; zfs?4eBXpU0k{V!(d0NcVdg7WS2Y%>5q)(7V`s#f=jO1QAcxs6MkqG;t(rBE|)EDZR zTBkie5;bP}lXdnN>a?{>m}zU5+MrPTLDeqJhiZ?gb|#z-Ytd+Mz#2XaZ6;IX8Etmf zGexey0Z7Kp1_0#8`(*C`4Q@V?gcYS=hvVlihb~XI95b0pzL(?#-%EmpWos~WerR$F zAbHWJlAz>8_DS+h!2l(NQe6Sp@HmNUlvcO~^2e-Lri;1Mxi(Zw@h6K0bn4*#SJ8w% z<3E>9=nl%VdL28=nov8;I<;?yS%+~7!~Ecv7-r?sFh@1aU}7!c_*np!5jw(T8SPIM zYehgOP0ing>r{m3n;NxE#EXb_fqA`Y4GV*o)SFRry($?x-++;&pxGydLHObV7X;@C<_XH6+hlC5xC9SvF%F7I_NGImW2gKLUa z$AAVD|78eXVGFNdz-blqv|449ekJ7uZ6G~0Rqnfv5w`6kqc(*w-$RI-%l=s}LEj1` z8hx5D1o|EnXHiS1)5r*lvqiF>Ll1*wew)U|XxQmkBwm3e$yc;EHi5p!M>^>pIBOG# z@UbQ>RnUal9R&z%6i1i5(|EQ+7I*JqX^7}etd35Y&cvii_*Y#WLn`gErX@Q)z4xrp zpK{YAI#%hLpD^fRY6;;f?eu4KvWhT!pziBn#tk+E3EDwmg`0y0%pac-mes#o^-k>1*E3`C?iau60o zxIlm~0Rm#jaP1&W6rU}Cx|32)NSO*q7^h+*gyx09YDm?4UUcI+z5m;7Tfpdv3w;K% znq8={YZx=%zl#Lm$u7g7GL?q8)z+bw!UIOQ9sOubmp@Q;4V0&xZsyQUNHNNwYF$I=3q8AaV zkTXm(VGJi%^D&PwQJ6iw#K}LcWUXOQ)i37!(ow2g@a3`hqUdOCzq=3 z#?ooo7uupph8fu=y21-zSOa|N0rk8W-giB)5bmAe zS9=9JY6Lrh!-uEe#N9!j6owwkJ7!X;`LpkO-X4(N&=wFPJF8tuLkC!mJRQUYuC78& z5q}clA6eOjmC{%a@+PD=CT}mamf<9}P-Ns1JKeqRLF5ME-g9oQldXaOyFuy*`U5d| zJ!O<{yZ?IjJZCEqNl5Kr?^YvXro%BB06d!NS?-FUrM4YG>&mFYE2p{x(2yZji+P)= z-JBj*{;<|U{2VX5_wIV2hQBqtSVta~F6-vkSH&N4Oq*q_-0OH%h@tMUFS{AgC$LK) z$`&hKcC&2{^q}6}Tu0MkoxEz#)%`{gkkAReg;r?LowcL%ods0VcUPUJk&}J*D!quLPuSb3eU)H6+tNy}LSJ~Qwt|pKwaxXEz%WEA|Y9Bm1nOyJ3k-~m1pUsZ}j0CIRJu0~hzS5;MgK?FZQ6@pEg zE^6HIRY=7R1$u1^i>!>2m<3RR+N{$$fNDrh2l{O70yLUluBJoNhbSJn6S=1Q?W%EuTPRQ=N7VC- z@sLyX`c?VNu4K9|HI&(tPG%FMnelW!dF@y#o5-g!>7i6^Y$UO_FTZyzna?ItdGoY8 zF*2SUN~SZTsnNvtr1{e~l*lKN*XEPibYi4$JUcR!%nfE!V=5(`7)>Vf`D|)nJfF-B zBnEeF&r;7&-(Y4WlTD;4K*^MAZ)Q9{K9JO7HnTS|lHc1mmdp+&(|IZ?yh-dGWM(-l6~fVawwNi zWNFhdwT+}kQ~A-{_6%)LM+BUp|n?B^z_u!NzOGli9ru*_`7z zA9HJ+#rSvNX5hAIjyI%-Ge`E$`3-3+Nb|Js57Odft|67_DXO5Up}DJ}X+xTsPYroy ztcR1?9#8%85@}v#yun0TEgs0^cX$IyZ&N0nJS$Wyi(u!4nx4EiIS6Q&#t)HaDS0jp zIZh3J5Ki&jiVNeaaS`7|@yl=t?_3M4lVfI}%F8D6@a*#0{ z+3Uo}tDlQ2$2DfhbNRu>!NHD>#86vDS9g1RXLDy_pu44`scEpYvuP;NHQ3zI)SPG= z9&T-I97zpi6WP6ui4nliOhgVyPj6ReYQwe8`IPxS26!629Z|sE&S77wFeQUpce(Mg zv5~z4iIGHlQ0v6{eSLP;QbUQcv212{5^&Ly4MKyN+~}S}ZnQ6#AL{90L5z>&b3HwU zO6;4So;7~07nu|*kCBbkW0`a=+0#Qh^R((1DPLLz1F1Bl)YH>z{8fVt7gN%28`IM> zp5Bv9j4fW$?`6`OsQ$ItY`th5{Tf?-*|G9BOG97)Ug?H#Id61C4gXmNR0@n;Y62noK@`B9qPMn7GeGYMp-S z`77LMxam0k1S7RLt*Mi6C*x+~PQewYnMHUuZVqlPZXRwvZUJr~t~l+fgoFBC$Fu4S z!cY5Q=39Wfb~lJXsCW{Y#sjpvE4kNddybQ(^J?Mf~5{p$g=V?X4mfN*=+okgL_)KyPEq7W%cx2kjy8v->+IVX!gd$ zzzEqki-O4QNR3UwE&leJ1S!SYvB{&2tF#rlpb1kV;}+!&t;=NNBO{ZEI$N3x1zccu z_#n>U;hvt|$-$nUOOk`M-qywr3-+-%b=C7GGQ(mkPK->!eo!hqz*cr1dV2f`8QfFc zo?r=T!wp&$w89^Gza5jYEtB{;Sh=O6MDP7fg`qlDC;U3d@d`{Zvo&@0%}B1L(jC1A24cPv;an%^~M&^Dx@#nSl{3-p5Ac02Ta zqLX@hh{)p=2Ii$h{CH~%KtG;OjR4Pvelui7PtV!{)f`N=>3az@1v`)3tA)xblca$q|--Pw5By{%xng!3QN(C(@3thw3sR5C1QhR zUTOQY0WFdo9m})#ua&oI4ZCk9NBIMZ^sYgOt&AaGdI|ATWO+UlkoJ}z8GwGf6bgrE zpHd9AHIr^Mx80EOsmW()3Jw9p)xm=;~BL6IVlDAA4 zVP%;NnI||7|6Q)Ylo*CYxYn6oQ|nZM`{&||Hd%r%x@0B3_QCVRrD%>e`9uX;UGP5Gy5|YSrtwF$`s=Wd0 zX5$1viNV3-Sbj2`g|8on|CoH^IKQ1R5UPFi!b`Ou;cT*2&Z`$9kLj=1SdZ3 zEL?HiGCvOCh|_?Z!d^QQlr1=WBfjABcxnATQ27WMwkMa5jg03Y_gj2&ABtJD{+-m* zPdyuOqWhq&g|5WW=Eet%Ai>*{f~SS^$_|fY_B@YFqrMEYzqk7Fci;=B+=DM%@mYMOdkA0i{}1@$bGAt|6cB}k8*wUE zWi{a>12`UjqJ{kWiJpI@`H9b*RLW1ZQis|t*M@7yb>NC=@QyZ1f-gSVj!zf9(sONv z5BS0Kw#UrWh@W6{#0LS8X)?IqD_ zKGqK?D+mjpRJ3>;al>&69*&8O#^5WA_{&*-ip595pDzj@ov=0;IZ86uIEp|iWg7P| zZA;Ov*Wk4N$9BO&=e=PGbAz~XKkfp2{j_E`;Wp#8-~!lVYo*+&uvaSixsdc8PHW!C zeO{yp^uAeE{yCS*Uq#*^{70T8iwVLiUu*kV666;xHQt6`83JZ>%!1A<2EF1Cdb|}L zdsUAIO*Y%^i66$7+_D5v3&8uryyy$CFC_xS=Ub&cJx4B)M83}s8xNAVr<3fPv~|lI zyRTo4ueSH&o4wJOZHPbXXzTGNc&|NYlAW^L<6du45#Wu&Hb}@kkj(E%CevP%5kfaN zvDtix{Gu@eVYL-oklQK^JYO2&{D^dtdl{w#KOprcWotAXnd}K$UOxTd&3%dVhuVtM z9wWCEw+*MC*4o9mOK_Lsg0=Qa)P|Sjt{__rG|ip?TK8UQGaBU$g=w~ z>5JrVMk%x>u{USLn7MIC&Ros_h9ziAv`>_`kMgzVZ^jplycu8gLl6$)13!qLWXC7- zJVIX4Vp2jCYlMEydyU_de%ZhG{Q`+y;I$^(6Vy{X-@@`--=A8Rm{`j+ioLT>Vq)!+ zPu+`w%qDlkcIZi2lvv691UAy=Qwt2=HtJM=uJ-*MzMsVxZFapMegnSx_h#R})%V|l zul4sHe2r<)hdT*t-ASdB&lrx^sa;^pn2FC+JG1aL9~&8~Fn&R=#l%aFxsvz_{I!0* zAb*fAV0_FxC3DUQ=`_!Ie6=YE2l;|}r_OUwe^6f#4)RS+?`zwfC;WP*#s~EuD?TXy zf)YvN(d2wS5)SAE!yp+(&HRZQ^{Ra|g3ZK;72Bv_R?wP^_FVL;R_@{4w$P6EJMlGF zJ}xuT`#}ldCWW%jeWVf1{RMpS(?^xL`N%IQ$5wN6QC^V7$D6*=3B74S{|TRWs-3?k ze8J=uIQ@i&uEbr16RmJHPPz}lV;`;`m%s_$^lkt*h#SHsamd(C7}^aet#{Mre(JJx zR{XZFpbh`}tQX||$T5sltL3)icHl%6?ZgFK&n})vaHF`FtC>ubS3ixWR>>==nY{0` zQm&^6Jo8o-HRJ<_5i4GlMBTkx($ruHTQp%!2W(1kfCc7WNy{d47*qnLPyyz-&ku~z zr(hhf;aOCIut?B=+dT_ixn;J3j}q1@xE2?T^Io1`i<9Q;<&N`p%C~RuG5S-Gm73SgOmTcOu3&Utc=D z1^E{BJw}{%BdG^REa+LI4?1tnG0g7lJV!e1YG#MVuYQ#c2m7?mZ(-2iu>Dt7IaRum zCvs3ZGDGo(6Df4uJ>DoL6D!a5a>Z+eA_yd8-gv^+fyq>tJO@}xgQ=^>AjSud3{%qH4f#>yH{ zEXsL<<5}|LZCPkU$+Pr@^7zdU^8Copv(4y*Q@Qk_yqAF6FhbO#Mh37|eTL;O7V_$MB5>uM zwE29>4y=)G;W>c6xAJ^631{_UySFUBS6Z{57=`KO(urC7H?oLmLTBk z?fD%ijBHI|R)}C_1R;pD7F(9o8oF~K?GtVIcAPAcG)M2i-Hv-F?p?SO)~3nkI8V@? zLFzgMH^Ye^`aab3_o|9EIyjF~HA-;~?b1PbxhbJETpTa#E+`7pE3EiTdSoven=xa< z(-uC zYxtur)YXbJJ9|N?-tH zI69B;PO^aWkiKE5>c4fIL%i3H9LUDlc6YE?vdH+HXNc3v4dQaC?db%Tlh`kzYIG z#lFo}(kGSg;JtP_(?_UYzh6B0tyxb;FcG33{)??a>r38l86Tj%C9fcVO%u1Mg?_!1 zYic&80-}-vEcqUu&oy?>3=M{)Mht0;UX$KyF;8w=UTgT=ns8^Jv2-3I-E886^y0L-ae;jB#mM5{OZtF^e_v5q8WT}> z&$rftdS45moXd5)=Pt=7X%yU{ghb@ zHxeCT!d{q^qpbMxVT`IhQT)dVKu1GF+f(Ue<7j3`kn>lKwMHf*&bN3zF5b4T>jS(C zc9IYB9HhOGXO7`MbO_A;1NZr6`yNsTG||U+z8Cj#+{>kj?jx^$CxRw=u&J0Pihtqf z^v-p;Qc@4M)E@6VVD!Uw(ACgvc7p*e-o|WVD0MBfa9MM$5s-Zc$*Q`huztr`=L;c^ zmi7)RFPguh)b7*}s+7G3g*nb6v_nYcm;PeCpXUIOKfyC%iPW&HUxi`}p6u~PT51i@ z_{+j$bI``%$3i9(FBYX_LxL#0hxbK`&+9cxAkSLR6aNtLLR`V3m(i(NAOWS896H z5I?!$BIWZ3*3Ok5IG2gp3gWVKI07ff`4mp`AoppUou<;d{}=E564ocL^`9=z4|i?K zf5cj%OizN&e5123A!%ukn#BnLS%~WVh}Z@gd66xJDa!W4mP)--s_3^HzMZj6tb1 zHIudCR8|s%9C5+}a({y}QR$&(-)}jxU8V%nHjS~?=ofMJ7=RDp7G?^Idq#&9#hiw( zJjLTM*`D;!7;VkrcH{QquEX7cORCM;Bqpb<5&wLMbPB#rrDhB1u@b=sQ-@&w7JT)a ze#Lv&oV#}2dFwa4`uvR-Y}&l#!i%aNtjC+y4Rirz|=IdFp@@zks@H z87G}Q^ORY$=ghSU=FMNQ@YK`1y82h0e#V)L7B5+P*0SXdjcUS+toFnvOHI+0JHP6* zI3Pg!Q_cY8_U15VL*8ypEw-AVCHAJ+=-VVO`Pk5uQ$4a}GQXnj_K~eh2Qq;Hlq371R}V?&ubRPW;Y4knnBAR1&6^!+97w z{*+h~9_Ma9a5M_Ts0NdU(sP`z(S@rSmN|yZh(Gj4TK3nmqCOb&9(44j?IOoRxM1Ud znCHL6eGT_=2Uv$o>;Wwp!A7L1DXc3nKOG;{P_tR~)Eesr$t{Egr=IM2f_M=Nf52D# z5i(8QMOIiDQ;_DR$TS!GdAsqoX&1{=gSa8$1iZ&NZNYk-!r|qt0zd*D>X@Le1pYjn zHu~bQ5URiB7$KCOvmh~utgJQpf;^q1my{$3i~Ca_eT)K%FgSfOXwUwoGksWV>?oXA zoD2^o{h=LC`$CuGP*4ixuBU#@)us4q`*z>ogRk+s314#5H{na_P`t4`#yj=z2Y#Ah zqY2(W$$KqyZ9I{)tz6RIfSg*wDpxy^=f{1WaDZ^W!Sgq9$AfUbMSlGRgReBgc?)em zpK`5?HvZI~S*@=x#v@0d)8mB1qaqNWO?0YPS(()*Ebf^2%Zo&R4=CZQig3)aupg2_ zC4KyqBhqGdUb_?}orsumTGz2DD=lsCE;8$a6RpdFZdyeI`#0>kS~HN`k=UJ58)!;V-duyX zE#q;5JkKs;GMm%;d9GsM_@;;0S<APP-qPnr8>a1%o|OBnc;dlO~tSwT+U^5qX72i z9`=ErUkg_VAS!+mcqs?-94GuAW3T0A1^=}7v%S_5CNr*z z#o0_bJH|)3JfozH+H-9?{4<5yG8qHs1wr)=j2e<@AVCwr{{+iNLJKpwmt4@$ME)+? z5RAz<3sr)IApCYeyw(UkjP#_1`xIDdL&#--iNaia964@3c14tV8+FBt%Ko@twl4;l zl<7|*ffs7N^CV@iC@S;5DeeExl<*^d_#!S4VEvdwXpBnUOQV4H#<0#{RZw34+FEmR z|HQ!JD7eYq-Eok5`l#<5oc0~RU4BCh8lqv2^9<=EPz%zFo>TgO`(C`xGT%$_^?o(J zeh3j*@FO0#py-MeR=m}f0s&U))v$K+Iz-c0t`tOC32y{jhNDHGVi?#7HaS|{^Og7N zt(!Ob2yLx@6Ng0!lg$EaVBeka`WN*q>Tf8dN*H_t3I_hRYY8qsx2vh?=M(QZw|CvT zC6nn4f|*)cl4D%-ScNWI#7z@fJ-w#1c&rXeN?&73M``$yOE(o=UtBz$lAMr5Uua35 zTVG%_`iFJ(3lBmVUcaEPsMkmK#sDfQi$>C4HXirxBoII5MA5S#8-n+6iUVNPASl6O z@H`GSk|5OlF|gLK*-Wh2hJ3>t1h4jD6C;?TZZI6x1T(?Du_HCO!)&}}7ZX-7&C>?$ zZ+%QDZK5i3V+?ZF{G?C5P9cDB!)^MEb7zyrBa{102JGQP~LB`+i%lNsXC!n6UY^XJs zt*5i@DxCOZ?|9g$diZ&1`5?!Ba!6MdgslxH3jefNs zZsmCi(v5f0ll|c$n)v8)5RQ>8m-Icpbo4;Lp;Gw>7i^3H?77Ay3s=`j znd_0hKwVc-PqV2j{=gl~#HXGYrjB#8j;TuAF53dG`WhS0j%B!l%IZ=O7Yq*@_14CX zwZ>9+kd|uRg7AlVKFNtc^;d$SvKJiVqMXt+YkY%}ZsS?>+6E{&?tsx9B$iSzrXUc( zNlXhsxm_RtQDrjIk%k9SSFFMg1Q;MK9qr{Fn3OMCwI&z2whL;_shR>AZ%93~PNE0E zUgK%RE+8gR&cbJqfX;2?Sz6S-*Yhm64cdDN&st4E_;Q{#k3skXo@W$=*YK?V1@R3$ zFDVLZ?aalUfEiYo4A0iK$w~m;NIe?+V8<{fPwZC1!(zc2oI6RUw%(7gbf3eAv~t!4 z*q+lg!6sm4CgF7~AHXuQz&|%QkCErBqB_hp*&{oA%hf9Grj{SHXAFXvy~1fCo#aj@ zU`&hx{pe6{<#km1!Z?F8>uKXP_@XO2xrgsgR>B|W7Oe#OQY!f<&LId0!jcj;7KODU z1VKT(Flupng~ee6@$a7!ukhk2@q(}*{fBriF8_ZKUQ`sXu%wDXda2U{4MF$;o=+|c z|Cnb0lcw%>`Sl0kI|#4C6^B-E3ZDzsUc^~a%g%aa;EFzDCPIh(?bjZPpxp0JzIMYy_=2(E9!2itGh=RY z3$b2owK3ahhj59{NdW4p;k||xFmvwh$Ygf;_fc9X@C8j$k1VE)wxiTxaw;A543S0> zSi!973BngLF~TW9_#(om5`G+4jnmxx9H)5-=1%LrIQ#_RU*LX;6D_1Xzry_*Cmg4r zVCdg*|A7nUTlnNRxZh5B|2x9Rt%aMM>taxHUU!Lwr6&C1`48sD%!`?!Y+_Fz*Q_yi zFq{ciAM!gaQFKQN?R${?+AHqF*SOAN+@kmi3B@pFGy+$n1bo2@JDsPIWFoo#wdN&d z9i(i*>oxe&3T(qydoIRT|5|C7;Mh=^hFUD0%l{;99cOE0-D0F?gteaqF!TqWU&0#m zmw^>0h)R`hp%Lg>k+0>|gPAo#_^F~ED-f{4N}1M(RvtFp_N=LmF-|H zU_fOJtBE#Dy$ML(uq0@YkQV*@#bp-Of@vynK$Ec9AgXuvm>_rY8~%ky7wq8B{%Hq2FUEHqr4QEmVV+;pbnQ`x zf$bi!Bo(qYmH{+hVTw5g@3wW+PCy{V(Av#G18ySb^kxw)mewYjaiy}6^gv$?Ce zyQQh6xuvD0wWY14y``h2v!$!0yS1scxwWOWwY9Cay|tsYv$dw-u zr8?8a*|+BIpwIu#1PgZ*kC`Uj#f5Os0t@qr5B91cJRd|pkM}`%CgFO*+!YPDTN#?2 zW^^_NAZ&~PHwQssc52HJdLvibx!;FBSq6v1d_Z}C_kzwK-sZQZPl}Zdbdkx(n4QPS zGmAXG#24-emdAL0czIVrf+s)?c2C{6Y|D&XWi|Y#;tM9FnbBp@$V6>+!=eRJK#Lk| zPNc!)5vS_@zx;FJpW`!qRjqsh>3M$PDZhw*j`_l0)t6>n+0fAN8q-&QCRwpki6Ie0 z#%)(PHxIASF+8Hs|4IAmEjD=CTcW}3?`JIbzQ&%JIDmg9;d}A5*L)gZ^xGHk0X1g; zO+i{4hNgb89+p^BZcVtvmHnJeA?-BM{vKaz{Aql_Mo@+tQi6d@D<<2p_-YFmLHZ*Q z1K2&F(=H>eU_VUbmf;_f))($Ja%VZWs3Wj2=)^fdKGEh{A04?2b#Xp9A82Yh$DEfHlSCL7KYX>RLTyKcj) zH*FqDUiG=p&tDKLudJFmyQ913o{# z@YZebd2d7GqQw`#|IWKU{E@rwx&Mm~{_nD?>Qff>oU``AkKX;r-`^RVJFotXRpIlbc4=vmQoBh!{n+*@{fMUm=?j&M(OUMx}_+p?jvwWc-J zP+qzJ%!|%Ht9-xrocQR~^=qpt%W6*UDXZ*Q7MVTqH!Fv>RJ$`AbG(uxoLYJcl=cVXGINcsM^yfLyXS`)5_ z)xN#|yo&tFiKi=b@C^=UJDqVE33mfrZwiT_%%F;W=`-8AFejb~5%?aDGYa&dHiTWJ5ZWs#xkODZQm z(Y3H7P>d`@$&x({WF00!^Ro?&=UnxgzMmhs<*jdf`^P@@#V>vR8{huBpFZ)6!%oBibZ5_svp2l@H3!~G z9i9rq{puBOm?BSHJ$vM}Pd!>+ksT-+$w~ zk8aqs`O?d;?t9}~Z~fHgKL6E+zwyl<&X_g(%B!CKujdX=j9&B8pG`Y0omsH3@A`e8 z_~Z>=dT`e4Q%_rW-lolh|9v-n_UqsO!B3w0&p%~zx8}#+b!J23-JksYSHJn_4}bQa z)$hKe>DJT!;rrh`ylL|lSH{Yx*Dh-O?eEf=&a=O+B=xG)E=ZEK(yOG97TO<~CV`Z@!m0PBt6uUSUjx4CG z2$zRr;SjjLIuZ?6mATVSiEfI`k6juImCdf+5?K>o4tknVHodwhvha*PZ#1&=jEQeW zZ+sv;uk6OZgfEZHs+dzDfZJJCSvIfi^4M9?b(PB^z(%;aYFT7nSyg!AKB5|%F9=V3 zqCpRb9cjKRvj4|t#;T*yiI3Lq|5MEMmX;BFOJw3J;rZd|HOIu^J}x&O z+W?KPAF?OWw}7)3IZ*ZRTIzDi?zvD0N;~j2gUFYdFk9U52TB5sg z&RyM23li)9aOzzfSGOg$Jhk(#3pZ!#E_(licU|N>n%J8B-d$UrAJ=Vj4n2PHCw`u| z^vNgcE`RLTcU|r|zrFk^_l7GtI2Uu4Lj;BR=dQ16I;GZ40$-t!8+ny`>ijFKdMYa1 zIT5#ltuT64cxCz0Ij+}9hDbSZ6srs^bbFLNQcjY}&^$h8*Ug?82?4k6si836U?dzR zfjcuaiyf8JlwIz|!j+*@-4*1mCg);`r_^v1h>nG-OsQ%Tm4*~v5bCCVK`jg2^=<@1 zcGoR;FLXn(>hb|MR8bY%5SmYUuG=}yrN(HLdwPXC9C6ENRA_D}60VKZ@L1+fcNzQe z!qBPwTg@kb%K40Bh0AJk$3yk*?rO{XPt!ne5no>P_zIT4p{n{Ek#cWL|FP}F^Q zXx>RR?wRFts~W;h^eq%xO)=)Ai z?)%+v`6*^(U3Zo{Ef$V`tz4a%tx;vJl+F$P2W>0EpC7uoTyJ)2Jcvz(nbfFL;fDUi z%mWebZPXWWy~@R9W~RzQ;RXiWi7_DVMYCuMrM$L`3K(;sO;x!Lv)dMp>d7se?to$( z_ngRuymuNxvmwwqu25bcik%v{J?wNwTFTvN?yRUgol<9*5~D-zo#Z(?!U)7hV^06X cQ;wlu7qY}e#|Ewu9_eCS7Iz2kE0@*&A3F+e3;+NC literal 0 HcmV?d00001 diff --git a/contracts/wasm/cw2981_royalties.wasm b/contracts/wasm/cw721_royalties.wasm similarity index 100% rename from contracts/wasm/cw2981_royalties.wasm rename to contracts/wasm/cw721_royalties.wasm diff --git a/example/contracts/erc1155/ERC1155Example.abi b/example/contracts/erc1155/ERC1155Example.abi index 7941ac8f6..139156a2f 100644 --- a/example/contracts/erc1155/ERC1155Example.abi +++ b/example/contracts/erc1155/ERC1155Example.abi @@ -1 +1 @@ -[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/precompiles/wasmd/wasmd.go b/precompiles/wasmd/wasmd.go index 73d24fa78..ddff9279d 100644 --- a/precompiles/wasmd/wasmd.go +++ b/precompiles/wasmd/wasmd.go @@ -354,7 +354,7 @@ func (p PrecompileExecutor) execute(ctx sdk.Context, method *abi.Method, caller if caller.Cmp(callingContract) != 0 { erc20pointer, _, erc20exists := p.evmKeeper.GetERC20CW20Pointer(ctx, contractAddrStr) erc721pointer, _, erc721exists := p.evmKeeper.GetERC721CW721Pointer(ctx, contractAddrStr) - erc1155pointer, _, erc1155exists := p.evmKeeper.GetERC721CW721Pointer(ctx, contractAddrStr) + erc1155pointer, _, erc1155exists := p.evmKeeper.GetERC1155CW1155Pointer(ctx, contractAddrStr) if (!erc20exists || erc20pointer.Cmp(callingContract) != 0) && (!erc721exists || erc721pointer.Cmp(callingContract) != 0) && (!erc1155exists || erc1155pointer.Cmp(callingContract) != 0) { return nil, 0, fmt.Errorf("%s is not a pointer of %s", callingContract.Hex(), contractAddrStr) } diff --git a/x/evm/artifacts/cw1155/artifacts.go b/x/evm/artifacts/cw1155/artifacts.go index c05e89917..a1531af65 100644 --- a/x/evm/artifacts/cw1155/artifacts.go +++ b/x/evm/artifacts/cw1155/artifacts.go @@ -12,8 +12,8 @@ import ( const CurrentVersion uint16 = 1 -// //go:embed CW1155ERC1155Pointer.abi -// //go:embed CW1155ERC1155Pointer.bin +//go:embed CW1155ERC1155Pointer.abi +//go:embed CW1155ERC1155Pointer.bin var f embed.FS var cachedBin []byte diff --git a/x/evm/integration_test.go b/x/evm/integration_test.go index f28397768..74d8d6ac1 100644 --- a/x/evm/integration_test.go +++ b/x/evm/integration_test.go @@ -19,6 +19,7 @@ import ( "github.com/sei-protocol/sei-chain/precompiles/pointer" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw721" + "github.com/sei-protocol/sei-chain/x/evm/artifacts/cw1155" "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/types" "github.com/sei-protocol/sei-chain/x/evm/types/ethtx" @@ -26,13 +27,13 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) -func TestERC2981PointerToCW2981(t *testing.T) { +func TestERC721RoyaltiesPointerToCW721Royalties(t *testing.T) { k := testkeeper.EVMTestApp.EvmKeeper ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) adminSeiAddr, adminEvmAddr := testkeeper.MockAddressPair() k.SetAddressMapping(ctx, adminSeiAddr, adminEvmAddr) // deploy cw2981 - bz, err := os.ReadFile("../../contracts/wasm/cw2981_royalties.wasm") + bz, err := os.ReadFile("../../contracts/wasm/cw721_royalties.wasm") if err != nil { panic(err) } @@ -132,7 +133,7 @@ func TestERC2981PointerToCW2981(t *testing.T) { require.Equal(t, adminEvmAddr.Hex(), ret[0].(common.Address).Hex()) } -func TestCW2981PointerToERC2981(t *testing.T) { +func TestCW721RoyaltiesPointerToERC721Royalties(t *testing.T) { k := testkeeper.EVMTestApp.EvmKeeper ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) // deploy erc2981 @@ -240,3 +241,223 @@ func TestCW2981PointerToERC2981(t *testing.T) { require.Nil(t, err) require.Equal(t, fmt.Sprintf("{\"address\":\"%s\",\"royalty_amount\":\"1000\"}", seiAddr.String()), string(ret)) } + +func TestERC1155RoyaltiesPointerToCW1155Royalties(t *testing.T) { + k := testkeeper.EVMTestApp.EvmKeeper + ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) + adminSeiAddr, adminEvmAddr := testkeeper.MockAddressPair() + k.SetAddressMapping(ctx, adminSeiAddr, adminEvmAddr) + // deploy cw2981 + bz, err := os.ReadFile("../../contracts/wasm/cw1155_royalties.wasm") + if err != nil { + panic(err) + } + codeID, err := k.WasmKeeper().Create(ctx, adminSeiAddr, bz, nil) + require.Nil(t, err) + instantiateMsg, err := json.Marshal(map[string]interface{}{"name": "test", "symbol": "TEST", "minter": adminSeiAddr.String()}) + require.Nil(t, err) + cw2981Addr, _, err := k.WasmKeeper().Instantiate(ctx, codeID, adminSeiAddr, adminSeiAddr, instantiateMsg, "cw2981", sdk.NewCoins()) + require.Nil(t, err) + require.NotEmpty(t, cw2981Addr) + // mint a NFT and set royalty info to 1% + executeMsg, err := json.Marshal(map[string]interface{}{ + "mint": map[string]interface{}{ + "recipient": adminSeiAddr.String(), + "msg": map[string]interface{}{ + "token_id": "1", + "amount": "10", + "token_uri": "testuri1", + "extension": map[string]interface{}{ + "royalty_percentage": 1, + "royalty_payment_address": adminSeiAddr.String(), + }, + }, + }, + }) + require.Nil(t, err) + _, err = k.WasmKeeper().Execute(ctx, cw2981Addr, adminSeiAddr, executeMsg, sdk.NewCoins()) + require.Nil(t, err) + + // deploy pointer to cw2981 + privKey := testkeeper.MockPrivateKey() + seiAddr, evmAddr := testkeeper.PrivateKeyToAddresses(privKey) + k.SetAddressMapping(ctx, seiAddr, evmAddr) + require.Nil(t, k.BankKeeper().AddCoins(ctx, seiAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10000000))), true)) + testPrivHex := hex.EncodeToString(privKey.Bytes()) + key, _ := crypto.HexToECDSA(testPrivHex) + to := common.HexToAddress(pointer.PointerAddress) + abi, err := pointer.ABI() + require.Nil(t, err) + data, err := abi.Pack("addCW1155Pointer", cw2981Addr.String()) + require.Nil(t, err) + txData := ethtypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(1000000000), + Gas: 5000000, + To: &to, + Data: data, + } + chainID := k.ChainID(ctx) + chainCfg := types.DefaultChainConfig() + ethCfg := chainCfg.EthereumConfig(chainID) + blockNum := big.NewInt(ctx.BlockHeight()) + signer := ethtypes.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix())) + tx, err := ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx, err := ethtx.NewLegacyTx(tx) + require.Nil(t, err) + msg, err := types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + txBuilder := testkeeper.EVMTestApp.GetTxConfig().NewTxBuilder() + txBuilder.SetMsgs(msg) + cosmosTx := txBuilder.GetTx() + txbz, err := testkeeper.EVMTestApp.GetTxConfig().TxEncoder()(cosmosTx) + require.Nil(t, err) + res := testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, cosmosTx, sha256.Sum256(txbz)) + require.Equal(t, uint32(0), res.Code) + pointerAddr, _, exists := k.GetERC1155CW1155Pointer(ctx, cw2981Addr.String()) + require.True(t, exists) + require.NotEmpty(t, pointerAddr) + // call pointer to get royalty info + abi, err = cw1155.Cw1155MetaData.GetAbi() + require.Nil(t, err) + data, err = abi.Pack("royaltyInfo", big.NewInt(1), big.NewInt(1000)) + require.Nil(t, err) + txData = ethtypes.LegacyTx{ + Nonce: 2, + GasPrice: big.NewInt(1000000000), + Gas: 1000000, + To: &pointerAddr, + Data: data, + } + tx, err = ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx, err = ethtx.NewLegacyTx(tx) + require.Nil(t, err) + msg, err = types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + txBuilder = testkeeper.EVMTestApp.GetTxConfig().NewTxBuilder() + txBuilder.SetMsgs(msg) + cosmosTx = txBuilder.GetTx() + txbz, err = testkeeper.EVMTestApp.GetTxConfig().TxEncoder()(cosmosTx) + require.Nil(t, err) + res = testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, cosmosTx, sha256.Sum256(txbz)) + require.Equal(t, uint32(0), res.Code) + typedTxData := sdk.TxMsgData{} + require.Nil(t, typedTxData.Unmarshal(res.Data)) + typedMsgData := types.MsgEVMTransactionResponse{} + require.Nil(t, typedMsgData.Unmarshal(typedTxData.Data[0].Data)) + ret, err := abi.Unpack("royaltyInfo", typedMsgData.ReturnData) + require.Nil(t, err) + require.Equal(t, big.NewInt(10), ret[1].(*big.Int)) + require.Equal(t, adminEvmAddr.Hex(), ret[0].(common.Address).Hex()) +} + +func TestCW1155RoyaltiesPointerToERC1155Royalties(t *testing.T) { + k := testkeeper.EVMTestApp.EvmKeeper + ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) + // deploy erc2981 + privKey := testkeeper.MockPrivateKey() + seiAddr, evmAddr := testkeeper.PrivateKeyToAddresses(privKey) + k.SetAddressMapping(ctx, seiAddr, evmAddr) + require.Nil(t, k.BankKeeper().AddCoins(ctx, seiAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10000000))), true)) + testPrivHex := hex.EncodeToString(privKey.Bytes()) + key, _ := crypto.HexToECDSA(testPrivHex) + abiBz, err := os.ReadFile("../../example/contracts/erc1155/ERC1155Example.abi") + require.Nil(t, err) + abi, err := ethabi.JSON(bytes.NewReader(abiBz)) + require.Nil(t, err) + code, err := os.ReadFile("../../example/contracts/erc1155/ERC1155Example.bin") + require.Nil(t, err) + bz, err := hex.DecodeString(string(code)) + require.Nil(t, err) + data, err := abi.Pack("") + require.Nil(t, err) + txData := ethtypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(1000000000), + Gas: 5000000, + To: nil, + Data: append(bz, data...), + } + chainID := k.ChainID(ctx) + chainCfg := types.DefaultChainConfig() + ethCfg := chainCfg.EthereumConfig(chainID) + blockNum := big.NewInt(ctx.BlockHeight()) + signer := ethtypes.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix())) + tx, err := ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx, err := ethtx.NewLegacyTx(tx) + require.Nil(t, err) + msg, err := types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + txBuilder := testkeeper.EVMTestApp.GetTxConfig().NewTxBuilder() + txBuilder.SetMsgs(msg) + cosmosTx := txBuilder.GetTx() + txbz, err := testkeeper.EVMTestApp.GetTxConfig().TxEncoder()(cosmosTx) + require.Nil(t, err) + res := testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, cosmosTx, sha256.Sum256(txbz)) + require.Equal(t, uint32(0), res.Code) + receipt, err := k.GetReceipt(ctx, tx.Hash()) + require.Nil(t, err) + require.NotEmpty(t, receipt.ContractAddress) + require.Empty(t, receipt.VmError) + // set royalty + data, err = abi.Pack("setDefaultRoyalty", evmAddr) + require.Nil(t, err) + to := common.HexToAddress(receipt.ContractAddress) + txData = ethtypes.LegacyTx{ + Nonce: 1, + GasPrice: big.NewInt(1000000000), + Gas: 1000000, + To: &to, + Data: data, + } + tx, err = ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx, err = ethtx.NewLegacyTx(tx) + require.Nil(t, err) + msg, err = types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + txBuilder = testkeeper.EVMTestApp.GetTxConfig().NewTxBuilder() + txBuilder.SetMsgs(msg) + cosmosTx = txBuilder.GetTx() + txbz, err = testkeeper.EVMTestApp.GetTxConfig().TxEncoder()(cosmosTx) + require.Nil(t, err) + res = testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, cosmosTx, sha256.Sum256(txbz)) + require.Equal(t, uint32(0), res.Code) + // deploy CW->ERC pointer + res2, err := keeper.NewMsgServerImpl(&k).RegisterPointer(sdk.WrapSDKContext(ctx), &types.MsgRegisterPointer{ + Sender: seiAddr.String(), + PointerType: types.PointerType_ERC1155, + ErcAddress: receipt.ContractAddress, + }) + require.Nil(t, err) + require.NotEmpty(t, res2.PointerAddress) + // call pointer to get royalty info + query, err := json.Marshal(map[string]interface{}{ + "extension": map[string]interface{}{ + "msg": map[string]interface{}{ + "check_royalties": map[string]interface{}{}, + }, + }, + }) + require.Nil(t, err) + ret, err := testkeeper.EVMTestApp.WasmKeeper.QuerySmart(ctx, sdk.MustAccAddressFromBech32(res2.PointerAddress), query) + require.Nil(t, err) + require.Equal(t, "{\"royalty_payments\":true}", string(ret)) + query, err = json.Marshal(map[string]interface{}{ + "extension": map[string]interface{}{ + "msg": map[string]interface{}{ + "royalty_info": map[string]interface{}{ + "token_id": "1", + "sale_price": "1000", + }, + }, + }, + }) + require.Nil(t, err) + ret, err = testkeeper.EVMTestApp.WasmKeeper.QuerySmart(ctx, sdk.MustAccAddressFromBech32(res2.PointerAddress), query) + require.Nil(t, err) + require.Equal(t, fmt.Sprintf("{\"address\":\"%s\",\"royalty_amount\":\"1000\"}", seiAddr.String()), string(ret)) +} From 327d5fd9f7b7b028ab85ca39b22c8d4457c2cf51 Mon Sep 17 00:00:00 2001 From: davyli Date: Tue, 2 Jul 2024 17:32:59 -0400 Subject: [PATCH 28/65] Update cwerc1155.wasm --- contracts/wasm/cwerc1155.wasm | Bin 291992 -> 317508 bytes .../cosmwasm/cw1155/artifacts/checksums.txt | 2 +- .../cosmwasm/cw1155/artifacts/cwerc1155.wasm | Bin 291992 -> 317508 bytes x/evm/artifacts/erc1155/cwerc1155.wasm | Bin 291992 -> 317508 bytes 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/wasm/cwerc1155.wasm b/contracts/wasm/cwerc1155.wasm index a905d5e616d419c5a8cc58396b969e0c0536b327..017fc33038e3f0b75b0cf9bb4a86294ad10f8611 100644 GIT binary patch literal 317508 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ŢC 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