From a0a087a96a860d464d55d0e11d764136e17db71a Mon Sep 17 00:00:00 2001 From: Nadai <112663528+Nadai2010@users.noreply.github.com> Date: Wed, 6 Dec 2023 13:18:51 +0000 Subject: [PATCH] [i18n] translate Spanish (#142) --- po/es.po | 3086 +++++++++++++ po/messages.pot | 32 +- po/zh-cn.po | 10733 ++++++++++++++++++++++++---------------------- 3 files changed, 8829 insertions(+), 5022 deletions(-) create mode 100644 po/es.po diff --git a/po/es.po b/po/es.po new file mode 100644 index 00000000..a8d30b68 --- /dev/null +++ b/po/es.po @@ -0,0 +1,3086 @@ +msgid "" +msgstr "" +"Project-Id-Version: Starknet by Example\n" +"POT-Creation-Date: 2023-12-01T20:54:04+09:00\n" +"PO-Revision-Date: 2023-12-06 10:31+0000\n" +"Last-Translator: Nadai \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.4.1\n" + +#: src/SUMMARY.md:1 +msgid "Summary" +msgstr "Resumen" + +#: src/SUMMARY.md:3 +msgid "Introduction" +msgstr "Introducción" + +#: src/SUMMARY.md:6 +msgid "Getting Started" +msgstr "Primeros Pasos" + +#: src/SUMMARY.md:8 +msgid "Basics of a Starknet contract" +msgstr "Conceptos Básicos de un Contrato de Starknet" + +#: src/SUMMARY.md:9 src/ch00/basics/storage.md:1 src/ch00/basics/variables.md:8 +msgid "Storage" +msgstr "Almacenamiento" + +#: src/SUMMARY.md:10 src/ch00/basics/constructor.md:1 +msgid "Constructor" +msgstr "Constructor" + +#: src/SUMMARY.md:11 src/ch00/basics/variables.md:1 +msgid "Variables" +msgstr "Variables" + +#: src/SUMMARY.md:12 src/ch00/basics/visibility-mutability.md:1 +msgid "Visibility and Mutability" +msgstr "Visibilidad y Mutabilidad" + +#: src/SUMMARY.md:13 +msgid "Counter Example" +msgstr "Ejemplo de Counter" + +#: src/SUMMARY.md:14 src/ch00/basics/mappings.md:1 +msgid "Mappings" +msgstr "Mapas" + +#: src/SUMMARY.md:15 src/ch00/basics/errors.md:1 +msgid "Errors" +msgstr "Errores" + +#: src/SUMMARY.md:16 src/ch00/basics/events.md:1 +msgid "Events" +msgstr "Eventos" + +#: src/SUMMARY.md:17 src/ch00/basics/storing-custom-types.md:1 +msgid "Storing Custom Types" +msgstr "Almacenamiento de Tipos Personalizados" + +#: src/SUMMARY.md:18 src/ch00/basics/custom-types-in-entrypoints.md:1 +msgid "Custom types in entrypoints" +msgstr "Tipos personalizados en entrypoints" + +#: src/SUMMARY.md:19 src/ch00/basics/documentation.md:1 +msgid "Documentation" +msgstr "Documentación" + +#: src/SUMMARY.md:20 src/ch00/interacting/interacting.md:1 +msgid "Deploy and interact with contracts" +msgstr "Desplegar contratos e interactuar con ellos" + +#: src/SUMMARY.md:21 src/ch00/interacting/interfaces-traits.md:1 +msgid "Contract interfaces and Traits generation" +msgstr "Interfaces de Contratos y generación de Traits" + +#: src/SUMMARY.md:22 src/ch00/interacting/calling_other_contracts.md:1 +msgid "Calling other contracts" +msgstr "Llamar a otros contratos" + +#: src/SUMMARY.md:23 +msgid "Factory pattern" +msgstr "Patrón de la Factory" + +#: src/SUMMARY.md:24 +msgid "Testing contracts" +msgstr "Contratos de Testing" + +#: src/SUMMARY.md:25 +msgid "Cairo cheatsheet" +msgstr "Hoja de ruta de Cairo" + +#: src/SUMMARY.md:26 +msgid "Felt" +msgstr "Felt" + +#: src/SUMMARY.md:27 +msgid "LegacyMap" +msgstr "LegacyMap" + +#: src/SUMMARY.md:28 src/ch00/cairo_cheatsheet/arrays.md:1 +msgid "Arrays" +msgstr "Arrays" + +#: src/SUMMARY.md:29 src/ch00/cairo_cheatsheet/loop.md:1 +msgid "Loop" +msgstr "Loop" + +#: src/SUMMARY.md:30 src/ch00/cairo_cheatsheet/match.md:1 +msgid "Match" +msgstr "Match" + +#: src/SUMMARY.md:31 src/ch00/cairo_cheatsheet/tuples.md:1 +msgid "Tuples" +msgstr "Tuples" + +#: src/SUMMARY.md:32 src/ch00/cairo_cheatsheet/struct.md:1 +msgid "Struct" +msgstr "Struct" + +#: src/SUMMARY.md:33 src/ch00/cairo_cheatsheet/type_casting.md:1 +msgid "Type casting" +msgstr "Conversión de Tipos" + +#: src/SUMMARY.md:36 +msgid "Applications examples" +msgstr "Ejemplos de aplicaciones" + +#: src/SUMMARY.md:37 src/ch01/upgradeable_contract.md:1 +msgid "Upgradeable Contract" +msgstr "Contratos Actualizables" + +#: src/SUMMARY.md:38 +msgid "Defi Vault" +msgstr "Defi Vault" + +#: src/SUMMARY.md:39 src/ch01/erc20.md:1 +msgid "ERC20 Token" +msgstr "Token ERC20" + +#: src/SUMMARY.md:40 src/ch01/constant-product-amm.md:1 +msgid "Constant Product AMM" +msgstr "AMM de Producto Constante" + +#: src/SUMMARY.md:43 +msgid "Advanced concepts" +msgstr "Conceptos Avanzados" + +#: src/SUMMARY.md:44 src/ch02/write_to_any_slot.md:1 +msgid "Writing to any storage slot" +msgstr "Escribir en cualquier ranura de almacenamiento" + +#: src/SUMMARY.md:45 src/ch02/storing_arrays.md:1 +msgid "Storing Arrays" +msgstr "Almacenamiento de Arrays" + +#: src/SUMMARY.md:46 +msgid "Struct as mapping key" +msgstr "Estructura como mapping key" + +#: src/SUMMARY.md:47 src/ch02/hash-solidity-compatible.md:1 +msgid "Hash Solidity Compatible" +msgstr "Hash compatible con Solidity" + +#: src/SUMMARY.md:48 src/ch02/optimisations/optimisations.md:1 +msgid "Optimisations" +msgstr "Optimizaciones" + +#: src/SUMMARY.md:49 +msgid "Storage Optimisations" +msgstr "Optimizaciones de Almacenamiento" + +#: src/SUMMARY.md:50 src/ch02/list.md:1 +msgid "List" +msgstr "Lista" + +#: src/starknet-by-example.md:1 +msgid "Starknet by Example" +msgstr "Starknet by Example" + +#: src/starknet-by-example.md:3 +msgid "" +"Starknet By Example is a collection of examples of how to use the Cairo " +"programming language to create smart contracts on Starknet." +msgstr "" +"Starknet By Ejemplo es una colección de ejemplos de cómo utilizar el " +"lenguaje de programación de Cairo para crear smart contracts en Starknet." + +#: src/starknet-by-example.md:5 +msgid "" +"Starknet is a permissionless Validity-Rollup that supports general " +"computation. It is currently used as an Ethereum layer-2. Starknet use the " +"STARK cryptographic proof system to ensure high safety and scalability." +msgstr "" +"Starknet es un Validity-Rollup sin permiso que admite el cálculo general. " +"Actualmente se utiliza como capa 2 de Ethereum. Starknet utiliza el sistema " +"de prueba criptográfica STARK para garantizar una alta seguridad y " +"escalabilidad." + +#: src/starknet-by-example.md:7 +msgid "" +"Starknet smart contracts are written in the Cairo language. Cairo is a " +"Turing-complete programming language designed to write provable programs, " +"abstracting the zk-STARK proof system away from the programmer." +msgstr "" +"Los smart contracts de Starknet están escritos en el idioma de Cairo. Cairo " +"es un lenguaje de programación completo de Turing diseñado para escribir " +"programas demostrables, abstrayendo el sistema de prueba zk-STARK del " +"programador." + +#: src/starknet-by-example.md:9 +msgid "The current version of this book use `scarb 2.3.0`" +msgstr "La versión actual de este libro usa `scarb 2.3.0`" + +#: src/starknet-by-example.md:11 +msgid "For whom is this for?" +msgstr "¿Para quién es esto?" + +#: src/starknet-by-example.md:13 +msgid "" +"Starknet By Example is for anyone who wants to quickly learn how to write " +"smart contracts on Starknet using Cairo with some technical background in " +"programming and blockchain." +msgstr "" +"Starknet By Ejemplo es para cualquiera que quiera aprender rápidamente cómo " +"escribir contratos inteligentes en Starknet usando Cairo con cierta " +"experiencia técnica en programación y blockchain." + +#: src/starknet-by-example.md:15 +msgid "" +"The first chapters will give you a basic understanding of the Cairo " +"programming language and how to write, deploy and use smart contracts on " +"Starknet. The later chapters will cover more advanced topics and show you " +"how to write more complex smart contracts." +msgstr "" +"Los primeros capítulos le brindarán una comprensión básica del lenguaje de " +"programación Cairo y cómo escribir, implementar y utilizar contratos " +"inteligentes en Starknet. Los capítulos posteriores cubrirán temas más " +"avanzados y le mostrarán cómo escribir contratos inteligentes más complejos." + +#: src/starknet-by-example.md:18 +msgid "Further reading" +msgstr "Otras lecturas" + +#: src/starknet-by-example.md:20 +msgid "" +"If you want to learn more about the Cairo programming language, you can read " +"the [Cairo Book](https://book.cairo-lang.org). If you want to learn more " +"about Starknet, you can read the [Starknet documentation](https://docs." +"starknet.io/) and the [Starknet Book](https://book.starknet.io)." +msgstr "" +"Si desea obtener más información sobre el lenguaje de programación de Cairo, " +"puede leer el [Cairo Book](https://book.cairo-lang.org). Si desea obtener " +"más información sobre Starknet, puede leer la [Documentación de Starknet]" +"(https://docs.starknet.io/) y el [Starknet Book](https://book.starknet.io)." + +#: src/starknet-by-example.md:23 +msgid "Here's a list of other resources that you might find useful:" +msgstr "Aquí hay una lista de otros recursos que pueden resultarle útiles:" + +#: src/starknet-by-example.md:24 +msgid "" +"[Starklings](https://github.com/shramee/starklings-cairo1): An interactive " +"tutorial to get you up and running with Cairo v1 and Starknet " +msgstr "" +"[Starklings](https://github.com/shramee/starklings-cairo1): un tutorial " +"interactivo para empezar a utilizar Cairo v1 y Starknet " + +#: src/starknet-by-example.md:25 +msgid "" +"[Cairopractice](https://cairopractice.com/): A blog with a series of " +"articles about Cairo and Starknet" +msgstr "" +"[Cairopractice](https://cairopractice.com/): Un blog con una serie de " +"artículos sobre Cairo y Starknet" + +#: src/starknet-by-example.md:26 +msgid "" +"[Cairo by example](https://cairo-by-example.com/): An introduction to Cairo, " +"with simple examples" +msgstr "" +"[Cairo by example](https://cairo-by-example.com/): Una introducción a Cairo, " +"con ejemplos sencillos" + +#: src/ch00/basics/introduction.md:1 +msgid "Basics of Smart Contracts in Cairo" +msgstr "Conceptos básicos de los Smart Contracts en Cairo" + +#: src/ch00/basics/introduction.md:3 +msgid "" +"The following chapters will introduce you to Starknet smart contracts and " +"how to write them in Cairo." +msgstr "" +"Los siguientes capítulos le presentarán los smart contracts de Starknet y " +"cómo escribirlos en Cairo." + +#: src/ch00/basics/storage.md:3 +msgid "Here's the most minimal contract you can write in Cairo:" +msgstr "Este es el contrato mínimo que puedes redactar en Cairo:" + +#: src/ch00/basics/storage.md:13 +msgid "" +"Storage is a struct annoted with `#[storage]`. Every contract must have one " +"and only one storage. It's a key-value store, where each key will be mapped " +"to a storage address of the contract's storage space." +msgstr "" +"El almacenamiento es una estructura (struct) anotada con `#[storage]`. Cada " +"contrato debe tener un único almacenamiento. Es un almacén key-value, donde " +"cada key se asignará a una dirección de almacenamiento del espacio de " +"almacenamiento del contrato." + +#: src/ch00/basics/storage.md:16 +msgid "" +"You can define [storage variables](./variables.md#storage-variables) in your " +"contract, and then use them to store and retrieve data." +msgstr "" +"Puede definir [variables de storage](./variables.md#storage-variables) en su " +"contrato y luego usarlas para almacenar y recuperar datos." + +#: src/ch00/basics/storage.md:29 +msgid "" +"Actually these two contracts have the same underlying sierra program. From " +"the compiler's perspective, the storage variables don't exist until they are " +"used." +msgstr "" +"En realidad estos dos contratos tienen el mismo programa sierra subyacente. " +"Desde la perspectiva del compilador, las variables de almacenamiento no " +"existen hasta que se utilizan." + +#: src/ch00/basics/storage.md:32 +msgid "" +"You can also read about [storing custom types](./storing-custom-types.md)" +msgstr "" +"También puede leer sobre [almacenamiento de tipos personalizados](./storing-" +"custom-types.md)" + +#: src/ch00/basics/constructor.md:3 +msgid "" +"Constructors are a special type of function that runs only once when " +"deploying a contract, and can be used to initialize the state of the " +"contract. Your contract must not have more than one constructor, and that " +"constructor function must be annotated with the `#[constructor]` attribute. " +"Also, a good practice consists in naming that function `constructor`." +msgstr "" +"Los constructores son un tipo especial de función que se ejecuta solo una " +"vez al implementar un contrato y se pueden usar para inicializar el estado " +"del contrato. Su contrato no debe tener más de un constructor, y esa función " +"constructora debe estar anotada con el atributo `#[constructor]`. Además, " +"una buena práctica consiste en denominar a esa función `constructor`." + +#: src/ch00/basics/constructor.md:5 +msgid "" +"Here's a simple example that demonstrates how to initialize the state of a " +"contract on deployment by defining logic inside a constructor." +msgstr "" +"A continuación se muestra un ejemplo sencillo que demuestra cómo inicializar " +"el estado de un contrato durante la implementación definiendo la lógica " +"dentro de un constructor." + +#: src/ch00/basics/constructor.md:17 +msgid "" +"// The constructor is decorated with a `#[constructor]` attribute.\n" +" // It is not inside an `impl` block.\n" +msgstr "" +"// The constructor is decorated with a `#[constructor]` attribute.\n" +" // It is not inside an `impl` block.\n" + +#: src/ch00/basics/constructor.md:25 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x017fd6558e67451dA583d123D77F4e2651E91502D08F8F8432355293b11e1f8F) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/constructor/src/constructor.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x017fd6558e67451dA583d123D77F4e2651E91502D08F8F8432355293b11e1f8F) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/constructor/src/constructor.cairo)." + +#: src/ch00/basics/variables.md:3 +msgid "There are 3 types of variables in Cairo contracts:" +msgstr "Hay 3 tipos de variables en los contratos de Cairo:" + +#: src/ch00/basics/variables.md:5 +msgid "Local" +msgstr "Local" + +#: src/ch00/basics/variables.md:6 +msgid "declared inside a function" +msgstr "declarado dentro de una función" + +#: src/ch00/basics/variables.md:7 +msgid "not stored on the blockchain" +msgstr "no almacenado en la blockchain" + +#: src/ch00/basics/variables.md:9 +msgid "declared in the [Storage](./storage.md) of a contract" +msgstr "declarado en el [Storage](./storage.md) de un contrato" + +#: src/ch00/basics/variables.md:10 +msgid "can be accessed from one execution to another" +msgstr "se puede acceder de una ejecución a otra" + +#: src/ch00/basics/variables.md:11 +msgid "Global" +msgstr "Global" + +#: src/ch00/basics/variables.md:12 +msgid "provides information about the blockchain" +msgstr "proporciona información sobre la blockchain" + +#: src/ch00/basics/variables.md:13 +msgid "accessed anywhere, even within library functions" +msgstr "" +"se puede acceder desde cualquier lugar, incluso dentro de las funciones de " +"la librería" + +#: src/ch00/basics/variables.md:15 +msgid "Local Variables" +msgstr "Variables Locales" + +#: src/ch00/basics/variables.md:17 +msgid "" +"Local variables are used and accessed within the scope of a specific " +"function or block of code. They are temporary and exist only for the " +"duration of that particular function or block execution." +msgstr "" +"Las variables locales se utilizan y se accede a ellas dentro del alcance de " +"una función o bloque de código específico. Son temporales y existen solo " +"mientras dure esa función en particular o la ejecución del bloque." + +#: src/ch00/basics/variables.md:19 +msgid "" +"Local variables are stored in memory and are not stored on the blockchain. " +"This means they cannot be accessed from one execution to another. Local " +"variables are useful for storing temporary data that is relevant only within " +"a specific context. They also make the code more readable by giving names to " +"intermediate values." +msgstr "" +"Las variables locales se almacenan en la memoria y no en la cadena de " +"bloques. Esto significa que no se puede acceder a ellos de una ejecución a " +"otra. Las variables locales son útiles para almacenar datos temporales que " +"son relevantes sólo dentro de un contexto específico. También hacen que el " +"código sea más legible al dar nombres a los valores intermedios." + +#: src/ch00/basics/variables.md:21 +msgid "Here's a simple example of a contract with only local variables:" +msgstr "Aquí hay un ejemplo simple de un contrato con solo variables locales:" + +#: src/ch00/basics/variables.md:37 +msgid "" +"// This variable is local to the current block. It can't be accessed once it " +"goes out of scope.\n" +msgstr "" +"// This variable is local to the current block. It can't be accessed once it " +"goes out of scope.\n" + +#: src/ch00/basics/variables.md:41 +msgid "" +"// The scope of a code block allows for local variable declaration\n" +" // We can access variables defined in higher scopes.\n" +msgstr "" +"// The scope of a code block allows for local variable declaration\n" +" // We can access variables defined in higher scopes.\n" + +#: src/ch00/basics/variables.md:50 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x015B3a10F9689BeD741Ca3C210017BC097122CeF76f3cAA191A20ff8b9b56b96) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/local_variables.cairo)." +msgstr "" +"Visite el contrato en Voyager](https://goerli.voyager.online/" +"contract/0x015B3a10F9689BeD741Ca3C210017BC097122CeF76f3cAA191A20ff8b9b56b96) " +"o juegue con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/local_variables.cairo)." + +#: src/ch00/basics/variables.md:52 +msgid "Storage Variables" +msgstr "Variables de Storage" + +#: src/ch00/basics/variables.md:54 +msgid "" +"Storage variables are persistent data stored on the blockchain. They can be " +"accessed from one execution to another, allowing the contract to remember " +"and update information over time." +msgstr "" +"Las variables de almacenamiento (storage) son datos persistentes almacenados " +"en la blockchain. Se puede acceder a ellos de una ejecución a otra, lo que " +"permite que el contrato recuerde y actualice la información a lo largo del " +"tiempo." + +#: src/ch00/basics/variables.md:56 +msgid "" +"To write or update a storage variable, you need to interact with the " +"contract through an external entrypoint by sending a transaction." +msgstr "" +"Para escribir o actualizar una variable de storage, debe interactuar con el " +"contrato a través de un punto de entrada externo mediante el envío de una " +"transacción." + +#: src/ch00/basics/variables.md:58 +msgid "" +"On the other hand, you can read state variables, for free, without any " +"transaction, simply by interacting with a node." +msgstr "" +"Por otro lado, puedes leer variables de estado, de forma gratuita, sin " +"ninguna transacción, simplemente interactuando con un nodo." + +#: src/ch00/basics/variables.md:60 +msgid "Here's a simple example of a contract with one storage variable:" +msgstr "" +"A continuación se muestra un ejemplo sencillo de un contrato con una " +"variable de almacenamiento:" + +#: src/ch00/basics/variables.md:70 +msgid "" +"// All storage variables are contained in a struct called Storage\n" +" // annotated with the `#[storage]` attribute\n" +msgstr "" +"// All storage variables are contained in a struct called Storage\n" +" // annotated with the `#[storage]` attribute\n" + +#: src/ch00/basics/variables.md:74 +msgid "// Storage variable holding a number\n" +msgstr "// Storage variable holding a number\n" + +#: src/ch00/basics/variables.md:80 +msgid "" +"// Write to storage variables by sending a transaction that calls an " +"external function\n" +msgstr "" +"// Write to storage variables by sending a transaction that calls an " +"external function\n" + +#: src/ch00/basics/variables.md:85 +msgid "// Read from storage variables without sending transactions\n" +msgstr "// Read from storage variables without sending transactions\n" + +#: src/ch00/basics/variables.md:92 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x06eA827B32875483709b785A7F9e846a52776Cd8D42C3fE696218c2624b0DCCa) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/storage_variables." +"cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x06eA827B32875483709b785A7F9e846a52776Cd8D42C3fE696218c2624b0DCCa) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/storage_variables." +"cairo)." + +#: src/ch00/basics/variables.md:94 +msgid "Global Variables" +msgstr "Variables Globales" + +#: src/ch00/basics/variables.md:96 +msgid "" +"Global variables are predefined variables that provide information about the " +"blockchain and the current execution environment. They can be accessed at " +"any time and from anywhere!" +msgstr "" +"Las variables globales son variables predefinidas que proporcionan " +"información sobre la blockchain y el entorno de ejecución actual. ¡Se puede " +"acceder a ellos en cualquier momento y desde cualquier lugar!" + +#: src/ch00/basics/variables.md:98 +msgid "" +"In Starknet, you can access global variables by using specific functions " +"contained in the starknet core libraries." +msgstr "" +"En Starknet, puede acceder a variables globales utilizando funciones " +"específicas contenidas en las bibliotecas principales de Starknet." + +#: src/ch00/basics/variables.md:100 +msgid "" +"For example, the `get_caller_address` function returns the address of the " +"caller of the current transaction, and the `get_contract_address` function " +"returns the address of the current contract." +msgstr "" +"Por ejemplo, la función `get_caller_address` devuelve la dirección de la " +"persona que llama de la transacción actual, y la función " +"`get_contract_address` devuelve la dirección del contrato actual." + +#: src/ch00/basics/variables.md:109 +msgid "// import the required functions from the starknet core library\n" +msgstr "// import the required functions from the starknet core library\n" + +#: src/ch00/basics/variables.md:118 +msgid "// Call the get_caller_address function to get the sender address\n" +msgstr "// Call the get_caller_address function to get the sender address\n" + +#: src/ch00/basics/variables.md:120 +msgid "// ...\n" +msgstr "// ...\n" + +#: src/ch00/basics/variables.md:125 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/global_variables." +"cairo)." +msgstr "" +"Visite el contrato en Voyager](https://goerli.voyager.online/" +"contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/variables/src/global_variables." +"cairo)." + +#: src/ch00/basics/visibility-mutability.md:3 +msgid "Visibility" +msgstr "Visibilidad" + +#: src/ch00/basics/visibility-mutability.md:5 +msgid "There are two types of functions in Starknet contracts:" +msgstr "Hay dos tipos de funciones en los contratos Starknet:" + +#: src/ch00/basics/visibility-mutability.md:7 +msgid "Functions that are accessible externally and can be called by anyone." +msgstr "" +"Funciones a las que se puede acceder externamente y que cualquiera puede " +"llamar." + +#: src/ch00/basics/visibility-mutability.md:8 +msgid "" +"Functions that are only accessible internally and can only be called by " +"other functions in the contract." +msgstr "" +"Funciones a las que solo se puede acceder internamente y que solo pueden ser " +"invocadas por otras funciones del contrato." + +#: src/ch00/basics/visibility-mutability.md:10 +msgid "" +"These functions are also typically divided into two different " +"implementations blocks. The first `impl` block for externally accessible " +"functions is explicitly annotated with an `#[abi(embed_v0)]` attribute. This " +"indicates that all the functions inside this block can be called either as a " +"transaction or as a view function. The second `impl` block for internally " +"accessible functions is not annotated with any attribute, which means that " +"all the functions inside this block are private by default." +msgstr "" +"Estas funciones también suelen dividirse en dos bloques de implementación " +"diferentes. El primer bloque `impl` para funciones accesibles externamente " +"está anotado explícitamente con un atributo `#[abi(embed_v0)]`. Esto indica " +"que todas las funciones dentro de este bloque se pueden llamar como una " +"transacción o como una función de view. El segundo bloque `impl` para " +"funciones accesibles internamente no está anotado con ningún atributo, lo " +"que significa que todas las funciones dentro de este bloque son privadas de " +"forma predeterminada." + +#: src/ch00/basics/visibility-mutability.md:12 +msgid "State Mutability" +msgstr "Mutabilidad del State" + +#: src/ch00/basics/visibility-mutability.md:14 +msgid "" +"Regardless of whether a function is internal or external, it can either " +"modify the contract's state or not. When we declare functions that interact " +"with storage variables inside a smart contract, we need to explicitly state " +"that we are accessing the `ContractState` by adding it as the first " +"parameter of the function. This can be done in two different ways:" +msgstr "" +"Independientemente de si una función es interna o externa, puede modificar " +"el estado del contrato o no. Cuando declaramos funciones que interactúan con " +"variables de almacenamiento dentro de un contrato inteligente, debemos " +"indicar explícitamente que estamos accediendo al `ContractState` agregándolo " +"como el primer parámetro de la función. Esto se puede hacer de dos maneras " +"diferentes:" + +#: src/ch00/basics/visibility-mutability.md:17 +msgid "" +"If we want our function to be able to mutate the state of the contract, we " +"pass it by reference like this: `ref self: ContractState`." +msgstr "" +"Si queremos que nuestra función pueda mutar el estado del contrato, lo " +"pasamos por referencia así: `ref self: ContractState`." + +#: src/ch00/basics/visibility-mutability.md:18 +msgid "" +"If we want our function to be read-only and not mutate the state of the " +"contract, we pass it by snapshot like this: `self: @ContractState`." +msgstr "" +"Si queremos que nuestra función sea de solo lectura y no mute el estado del " +"contrato, la pasamos por instantánea como esta: `self: @ContractState`." + +#: src/ch00/basics/visibility-mutability.md:20 +msgid "" +"Read-only functions, also called view functions, can be directly called " +"without making a transaction. You can interact with them directly through a " +"RPC node to read the contract's state, and they're free to call! External " +"functions, that modify the contract's state, on the other side can only be " +"called by making a transaction." +msgstr "" +"Las funciones de solo lectura, también llamadas funciones de visualización, " +"se pueden llamar directamente sin realizar una transacción. Puede " +"interactuar con ellos directamente a través de un nodo RPC para leer el " +"estado del contrato, ¡y pueden llamar libremente! Las funciones externas, " +"que modifican el estado del contrato, por otro lado, solo se pueden llamar " +"realizando una transacción." + +#: src/ch00/basics/visibility-mutability.md:23 +msgid "" +"Internal functions can't be called externally, but the same principle " +"applies regarding state mutability." +msgstr "" +"Las funciones internas no se pueden llamar externamente, pero se aplica el " +"mismo principio con respecto a la mutabilidad de estado." + +#: src/ch00/basics/visibility-mutability.md:25 +msgid "Let's take a look at a simple example contract to see these in action:" +msgstr "" +"Echemos un vistazo a un contrato de ejemplo simple para verlos en acción:" + +#: src/ch00/basics/visibility-mutability.md:42 +msgid "" +"// The `abi(embed_v0)` attribute indicates that all the functions in this " +"implementation can be called externally.\n" +" // Omitting this attribute would make all the functions in this " +"implementation internal.\n" +msgstr "" +"// The `abi(embed_v0)` attribute indicates that all the functions in this " +"implementation can be called externally.\n" +" // Omitting this attribute would make all the functions in this " +"implementation internal.\n" + +#: src/ch00/basics/visibility-mutability.md:46 +msgid "" +"// The `set` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" +" // It can modify the contract's state as it is passed as a " +"reference.\n" +msgstr "" +"// The `set` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" +" // It can modify the contract's state as it is passed as a " +"reference.\n" + +#: src/ch00/basics/visibility-mutability.md:52 +msgid "" +"// The `get` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" +" // However, it can't modify the contract's state is passed as a " +"snapshot: it is only a \"view\" function.\n" +msgstr "" +"// The `get` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" +" // However, it can't modify the contract's state is passed as a " +"snapshot: it is only a \"view\" function.\n" + +#: src/ch00/basics/visibility-mutability.md:55 +msgid "" +"// We can call an internal function from any functions within the contract\n" +msgstr "" +"// We can call an internal function from any functions within the contract\n" + +#: src/ch00/basics/visibility-mutability.md:60 +msgid "" +"// The lack of the `external` attribute indicates that all the functions in " +"this implementation can only be called internally.\n" +" // We name the trait `PrivateFunctionsTrait` to indicate that it is an " +"internal trait allowing us to call internal functions.\n" +msgstr "" +"// The lack of the `external` attribute indicates that all the functions in " +"this implementation can only be called internally.\n" +" // We name the trait `PrivateFunctionsTrait` to indicate that it is an " +"internal trait allowing us to call internal functions.\n" + +#: src/ch00/basics/visibility-mutability.md:64 +msgid "" +"// The `_read_value` function is outside the implementation that is marked " +"as `#[abi(embed_v0)]`, so it's an _internal_ function\n" +" // and can only be called from within the contract.\n" +" // It can modify the contract's state as it is passed as a " +"reference.\n" +msgstr "" +"// The `_read_value` function is outside the implementation that is marked " +"as `#[abi(embed_v0)]`, so it's an _internal_ function\n" +" // and can only be called from within the contract.\n" +" // It can modify the contract's state as it is passed as a " +"reference.\n" + +#: src/ch00/basics/visibility-mutability.md:73 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x0071dE3093AB58053b0292C225aa0eED40293e7694A0042685FF6D813d39889F) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/visibility/src/visibility.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x0071dE3093AB58053b0292C225aa0eED40293e7694A0042685FF6D813d39889F) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/visibility/src/visibility.cairo)." + +#: src/ch00/basics/counter.md:1 +msgid "Simple Counter" +msgstr "Counter Sencillo" + +#: src/ch00/basics/counter.md:3 +msgid "This is a simple counter contract." +msgstr "Este es un contrato de un simple counter." + +#: src/ch00/basics/counter.md:5 +msgid "Here's how it works:" +msgstr "Así es como trabaja:" + +#: src/ch00/basics/counter.md:7 +msgid "" +"The contract has a state variable called 'counter' that is initialized to 0." +msgstr "" +"El contrato tiene una variable de estado llamada 'counter' que se inicializa " +"a 0." + +#: src/ch00/basics/counter.md:9 +msgid "" +"When a user calls 'increment', the contract increments the counter by 1." +msgstr "" +"Cuando un usuario llama a 'increment', el contrato incrementa el contador en " +"1." + +#: src/ch00/basics/counter.md:11 +msgid "" +"When a user calls 'decrement', the contract decrements the counter by 1." +msgstr "" +"Cuando un usuario llama a 'decrement', el contrato disminuye el contador en " +"1." + +#: src/ch00/basics/counter.md:25 +msgid "// Counter variable\n" +msgstr "// Counter variable\n" + +#: src/ch00/basics/counter.md:31 +msgid "// Store initial value\n" +msgstr "// Store initial value\n" + +#: src/ch00/basics/counter.md:42 +msgid "// Store counter value + 1\n" +msgstr "// Store counter value + 1\n" + +#: src/ch00/basics/counter.md:47 +msgid "// Store counter value - 1\n" +msgstr "// Store counter value - 1\n" + +#: src/ch00/basics/counter.md:54 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x01664a69Fe701a1df7Bb0ae4A353792d0cf4E27146ee860075cbf6108b1D5718) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/counter/src/contracts.cairo)." +msgstr "" +"Visite el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x01664a69Fe701a1df7Bb0ae4A353792d0cf4E27146ee860075cbf6108b1D5718) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/counter/src/contracts.cairo)." + +#: src/ch00/basics/mappings.md:3 +msgid "" +"Maps are a key-value data structure used to store data within a smart " +"contract. In Cairo they are implemented using the `LegacyMap` type. It's " +"important to note that the `LegacyMap` type can only be used inside the " +"`Storage` struct of a contract and that it can't be used elsewhere." +msgstr "" +"Los mapas son una estructura de datos de key-value que se utiliza para " +"almacenar datos dentro de un contrato inteligente. En Cairo se implementan " +"utilizando el tipo `LegacyMap`. Es importante tener en cuenta que el tipo " +"`LegacyMap` solo se puede usar dentro de la estructura `Storage` de un " +"contrato y no se puede usar en ningún otro lugar." + +#: src/ch00/basics/mappings.md:5 +msgid "" +"Here we demonstrate how to use the `LegacyMap` type within a Cairo contract, " +"to map between a key of type `ContractAddress` and value of type `felt252`. " +"The key-value types are specified within angular brackets \\<\\>. We write " +"to the map by calling the `write()` method, passing in both the key and " +"value. Similarly, we can read the value associated with a given key by " +"calling the `read()` method and passing in the relevant key." +msgstr "" +"Aquí demostramos cómo usar el tipo `LegacyMap` dentro de un contrato de " +"Cairo, para mapear entre una key de tipo `ContractAddress` y un valor de " +"tipo `felt252`. Los tipos key-value se especifican entre corchetes angulares " +"\\<\\>. Escribimos en el mapa llamando al método `write()`, pasando tanto la " +"key como el valor. De manera similar, podemos leer el valor asociado con una " +"key determinada llamando al método `read()` y pasando la key relevante." + +#: src/ch00/basics/mappings.md:7 +msgid "Some additional notes:" +msgstr "Algunas notas adicionales:" + +#: src/ch00/basics/mappings.md:9 +msgid "" +"More complex key-value mappings are possible, for example we could use " +"`LegacyMap::<(ContractAddress, ContractAddress), felt252>` to create an " +"allowance on an ERC20 token contract." +msgstr "" +"Son posibles asignaciones de key-value más complejas; por ejemplo, podríamos " +"usar `LegacyMap::<(ContractAddress, ContractAddress), Felt252>` para crear " +"una asignación en un contrato de token ERC20." + +#: src/ch00/basics/mappings.md:11 +msgid "" +"In mappings, the address of the value at key `k_1,...,k_n` is `h(..." +"h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)` where `ℎ` is the Pedersen " +"hash and the final value is taken `mod2251−256`. You can learn more about " +"the contract storage layout in the [Starknet Documentation](https://docs." +"starknet.io/documentation/architecture_and_concepts/Contracts/contract-" +"storage/#storage_variables)" +msgstr "" +"En las asignaciones, la dirección del valor en la clave `k_1,...,k_n` es " +"`h(...h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)` donde `ℎ` es el hash " +"de Pedersen y el valor final se toma `mod2251-256`. Puede obtener más " +"información sobre el diseño de almacenamiento por contrato en la " +"[Documentación de Starknet](https://docs.starknet.io/documentation/" +"architecture_and_concepts/Contracts/contract-storage/#storage_variables)" + +#: src/ch00/basics/mappings.md:28 +msgid "" +"// The `LegacyMap` type is only available inside the `Storage` struct.\n" +msgstr "" +"// The `LegacyMap` type is only available inside the `Storage` struct.\n" + +#: src/ch00/basics/mappings.md:44 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x06214AB4c23Cc545bf2221D465eB83aFb7412779AD498BD48a724B3F645E3505) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/mappings/src/mappings.cairo)." +msgstr "" +"Visita el contrato en Voyager](https://goerli.voyager.online/" +"contract/0x06214AB4c23Cc545bf2221D465eB83aFb7412779AD498BD48a724B3F645E3505) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/mappings/src/mappings.cairo)." + +#: src/ch00/basics/errors.md:3 +msgid "" +"Errors can be used to handle validation and other conditions that may occur " +"during the execution of a smart contract. If an error is thrown during the " +"execution of a smart contract call, the execution is stopped and any changes " +"made during the transaction are reverted." +msgstr "" +"Los errores se pueden utilizar para manejar la validación y otras " +"condiciones que pueden ocurrir durante la ejecución de un smart contract. Si " +"se produce un error durante la ejecución de una llamada de contrato " +"inteligente, la ejecución se detiene y se revierte cualquier cambio " +"realizado durante la transacción." + +#: src/ch00/basics/errors.md:6 +msgid "To throw an error, use the `assert` or `panic` functions:" +msgstr "Para generar un error, use las funciones `assert` o `panic`:" + +#: src/ch00/basics/errors.md:8 +msgid "" +"`assert` is used to validate conditions. If the check fails, an error is " +"thrown along with a specified value, often a message. It's similar to the " +"`require` statement in Solidity." +msgstr "" +"`assert` se utiliza para validar condiciones. Si la verificación falla, se " +"genera un error junto con un valor específico, a menudo un mensaje. Es " +"similar a la declaración `require` en Solidity." + +#: src/ch00/basics/errors.md:12 +msgid "" +"`panic` immediately halt the execution with the given error value. It should " +"be used when the condition to check is complex and for internal errors. It's " +"similar to the `revert` statement in Solidity. (Use `panic_with_felt252` to " +"be able to directly pass a felt252 as the error value)" +msgstr "" +"`panic` detiene inmediatamente la ejecución con el valor de error dado. Debe " +"utilizarse cuando la condición a comprobar es compleja y para errores " +"internos. Es similar a la declaración `revert` en Solidity. (Utilice " +"`panic_with_felt252` para poder pasar directamente un felt252 como valor de " +"error)" + +#: src/ch00/basics/errors.md:16 +msgid "Here's a simple example that demonstrates the use of these functions:" +msgstr "Aquí hay un ejemplo simple que demuestra el uso de estas funciones:" + +#: src/ch00/basics/errors.md:32 +msgid "" +"// Assert used to validate a condition\n" +" // and abort execution if the condition is not met\n" +msgstr "" +"// Assert used to validate a condition\n" +" // and abort execution if the condition is not met\n" + +#: src/ch00/basics/errors.md:39 +msgid "// Panic used to abort execution directly\n" +msgstr "// Panic used to abort execution directly\n" + +#: src/ch00/basics/errors.md:46 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x0022664463FF0b711CC9B549a9E87d65A0882bB1D29338C4108696B8F2216a40) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/simple_errors.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x0022664463FF0b711CC9B549a9E87d65A0882bB1D29338C4108696B8F2216a40) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/simple_errors.cairo)." + +#: src/ch00/basics/errors.md:48 +msgid "Custom errors" +msgstr "Errores personalizados" + +#: src/ch00/basics/errors.md:50 +msgid "" +"You can make error handling easier by defining your error codes in a " +"specific module." +msgstr "" +"Puede facilitar el manejo de errores definiendo sus códigos de error en un " +"módulo específico." + +#: src/ch00/basics/errors.md:85 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x0501CD5da5B453a18515B5A20b8029bd7583DFE7a399ad9f79c284F7829e4A57) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/custom_errors.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x0501CD5da5B453a18515B5A20b8029bd7583DFE7a399ad9f79c284F7829e4A57) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/custom_errors.cairo)." + +#: src/ch00/basics/errors.md:87 +msgid "Vault example" +msgstr "Ejemplo de Vault" + +#: src/ch00/basics/errors.md:89 +msgid "" +"Here's another example that demonstrates the use of errors in a more complex " +"contract:" +msgstr "" +"Aquí hay otro ejemplo que demuestra el uso de errores en un contrato más " +"complejo:" + +#: src/ch00/basics/errors.md:93 +msgid "// you can define more errors here\n" +msgstr "// you can define more errors here\n" + +#: src/ch00/basics/errors.md:125 +msgid "// Or using panic:\n" +msgstr "// Or using panic:\n" + +#: src/ch00/basics/errors.md:137 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x020C2da26F42A28Ef54ED428eF1810FE433784b055f9bF315C5d992b1579C268) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/vault_errors.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x020C2da26F42A28Ef54ED428eF1810FE433784b055f9bF315C5d992b1579C268) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/errors/src/vault_errors.cairo)." + +#: src/ch00/basics/events.md:3 +msgid "" +"Events are a way to emit data from a contract. All events must be defined in " +"the `Event` enum, which must be annotated with the `#[event]` attribute. An " +"event is defined as struct that derives the `#[starknet::Event]` trait. The " +"fields of that struct correspond to the data that will be emitted. An event " +"can be indexed for easy and fast access when querying the data at a later " +"time. Events data can be indexed by adding a `#[key]` attribute to a field " +"member." +msgstr "" +"Los eventos son una forma de emitir datos de un contrato. Todos los eventos " +"deben definirse en la enumeración `Event`, que debe anotarse con el atributo " +"`#[event]`. Un evento se define como una estructura que deriva el trati " +"`#[starknet::Event]`. Los campos de esa estructura corresponden a los datos " +"que se emitirán. Un evento se puede indexar para un acceso fácil y rápido al " +"consultar los datos más adelante. Los datos de eventos se pueden indexar " +"agregando un atributo `#[key]` a un miembro de campo." + +#: src/ch00/basics/events.md:6 +msgid "" +"Here's a simple example of a contract using events that emit an event each " +"time a counter is incremented by the \"increment\" function:" +msgstr "" +"A continuación se muestra un ejemplo simple de un contrato que utiliza " +"eventos que emiten un evento cada vez que la función `increment` incrementa " +"un contador:" + +#: src/ch00/basics/events.md:18 +msgid "// Counter value\n" +msgstr "// Counter value\n" + +#: src/ch00/basics/events.md:24 +msgid "" +"// The event enum must be annotated with the `#[event]` attribute.\n" +" // It must also derive the `Drop` and `starknet::Event` traits.\n" +msgstr "" +"// The event enum must be annotated with the `#[event]` attribute.\n" +" // It must also derive the `Drop` and `starknet::Event` traits.\n" + +#: src/ch00/basics/events.md:31 +msgid "" +"// By deriving the `starknet::Event` trait, we indicate to the compiler " +"that\n" +" // this struct will be used when emitting events.\n" +msgstr "" +"// By deriving the `starknet::Event` trait, we indicate to the compiler " +"that\n" +" // this struct will be used when emitting events.\n" + +#: src/ch00/basics/events.md:40 +msgid "// The `#[key]` attribute indicates that this event will be indexed.\n" +msgstr "// The `#[key]` attribute indicates that this event will be indexed.\n" + +#: src/ch00/basics/events.md:52 +msgid "// Emit event\n" +msgstr "// Emit event\n" + +#: src/ch00/basics/events.md:66 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x022e3B59518EA04aBb5da671ea04ecC3a154400f226d2Df38eFE146741b9E2F6) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/events/src/counter.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x022e3B59518EA04aBb5da671ea04ecC3a154400f226d2Df38eFE146741b9E2F6) " +"ojuega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/events/src/counter.cairo)." + +#: src/ch00/basics/storing-custom-types.md:3 +msgid "" +"While native types can be stored in a contract's storage without any " +"additional work, custom types require a bit more work. This is because at " +"compile time, the compiler does not know how to store custom types in " +"storage. To solve this, we need to implement the `Store` trait for our " +"custom type. Hopefully, we can just derive this trait for our custom type - " +"unless it contains arrays or dictionaries." +msgstr "" +"Si bien los tipos nativos se pueden almacenar en el almacenamiento de un " +"contrato sin ningún trabajo adicional, los tipos personalizados requieren un " +"poco más de trabajo. Esto se debe a que en el momento de la compilación, el " +"compilador no sabe cómo almacenar tipos personalizados en el almacenamiento. " +"Para resolver esto, necesitamos implementar el trait `Store`para nuestro " +"tipo personalizado. Con suerte, podremos derivar este trait para nuestro " +"tipo personalizado, a menos que contenga arrays o diccionarios." + +#: src/ch00/basics/storing-custom-types.md:10 +msgid "" +"// Deriving the starknet::Store trait\n" +"// allows us to store the `Person` struct in the contract's storage.\n" +msgstr "" +"// Deriving the starknet::Store trait\n" +"// allows us to store the `Person` struct in the contract's storage.\n" + +#: src/ch00/basics/storing-custom-types.md:37 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/storing_custom_types/src/contract." +"cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/storing_custom_types/src/contract." +"cairo)." + +#: src/ch00/basics/custom-types-in-entrypoints.md:3 +msgid "" +"Using custom types in entrypoints requires our type to implement the `Serde` " +"trait. This is because when calling an entrypoint, the input is sent as an " +"array of `felt252` to the entrypoint, and we need to be able to deserialize " +"it into our custom type. Similarly, when returning a custom type from an " +"entrypoint, we need to be able to serialize it into an array of `felt252`. " +"Thankfully, we can just derive the `Serde` trait for our custom type." +msgstr "" +"El uso de tipos personalizados en puntos de entrada requiere que nuestro " +"tipo implemente el trait `Serde`. Esto se debe a que cuando se llama a un " +"punto de entrada, la entrada se envía como una matriz de `felt252` al punto " +"de entrada y necesitamos poder deserializarla en nuestro tipo personalizado. " +"De manera similar, al devolver un tipo personalizado desde un punto de " +"entrada, debemos poder serializarlo en una array de `felt252`. " +"Afortunadamente, podemos derivar el trait `Serde` para nuestro tipo " +"personalizado." + +#: src/ch00/basics/custom-types-in-entrypoints.md:18 +msgid "" +"// Deriving the `Serde` trait allows us to use\n" +" // the Person type as an entrypoint parameter and return value\n" +msgstr "" +"// Deriving the `Serde` trait allows us to use\n" +" // the Person type as an entrypoint parameter and return value\n" + +#: src/ch00/basics/custom-types-in-entrypoints.md:37 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/custom_type_serde/src/contract." +"cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/custom_type_serde/src/contract." +"cairo)." + +#: src/ch00/basics/documentation.md:3 +msgid "" +"It's important to take the time to document your code. It will helps " +"developers and users to understand the contract and its functionalities." +msgstr "" +"Es importante tomarse el tiempo para documentar su código. Ayudará a los " +"desarrolladores y usuarios a comprender el contrato y sus funcionalidades." + +#: src/ch00/basics/documentation.md:5 +msgid "In Cairo, you can add comments with `//`." +msgstr "En Cairo, puedes agregar comentarios con `//`." + +#: src/ch00/basics/documentation.md:7 +msgid "Contract Interface:" +msgstr "Interfaz de Contrato:" + +#: src/ch00/basics/documentation.md:9 +msgid "" +"In smart contracts, you will often have a trait that defines the contract's " +"interface (with `#[starknet::interface]`). This is the perfect place to " +"include detailed documentation explaining the purpose and functionality of " +"the contract entry points. You can follow this template:" +msgstr "" +"En los smart contracts, a menudo tendrá un trait que define la interfaz del " +"contrato (con `#[starknet::interface]`). Este es el lugar perfecto para " +"incluir documentación detallada que explique el propósito y la funcionalidad " +"de los puntos de entrada del contrato. Puedes seguir esta plantilla:" + +#: src/ch00/basics/documentation.md:15 +msgid "" +"/// High-level description of the function\n" +" ///\n" +" /// # Arguments\n" +" /// * `arg_1` - Description of the argument\n" +" /// * `arg_n` - ...\n" +" ///\n" +" /// # Returns\n" +" /// High-level description of the return value\n" +msgstr "" +"/// High-level description of the function\n" +" ///\n" +" /// # Arguments\n" +" /// * `arg_1` - Description of the argument\n" +" /// * `arg_n` - ...\n" +" ///\n" +" /// # Returns\n" +" /// High-level description of the return value\n" + +#: src/ch00/basics/documentation.md:27 +msgid "" +"Keep in mind that this should not describe the implementation details of the " +"function, but rather the high-level purpose and functionality of the " +"contract from the perspective of a user." +msgstr "" +"Tenga en cuenta que esto no debe describir los detalles de implementación de " +"la función, sino más bien el propósito de high-level y la funcionalidad del " +"contrato desde la perspectiva de un usuario." + +#: src/ch00/basics/documentation.md:29 +msgid "Implementation Details:" +msgstr "Detalles de Implementación:" + +#: src/ch00/basics/documentation.md:31 +msgid "" +"When writing the logic of the contract, you can add comments to describe the " +"technical implementation details of the functions." +msgstr "" +"Al escribir la lógica del contrato, puede agregar comentarios para describir " +"los detalles técnicos de implementación de las funciones." + +#: src/ch00/basics/documentation.md:33 +msgid "" +"Avoid over-commenting: Comments should provide additional value and clarity." +msgstr "" +"Evite comentarios excesivos: los comentarios deben proporcionar valor y " +"claridad adicionales." + +#: src/ch00/interacting/interacting.md:3 +msgid "In this chapter, we will see how to deploy and interact with contracts." +msgstr "" +"En este capítulo, veremos cómo implementar e interactuar con contratos." + +#: src/ch00/interacting/interfaces-traits.md:3 +msgid "" +"Contract interfaces define the structure and behavior of a contract, serving " +"as the contract's public ABI. They list all the function signatures that a " +"contract exposes. For a detailed explanation of interfaces, you can refer to " +"the [Cairo Book](https://book.cairo-lang.org/ch99-01-02-a-simple-contract." +"html)." +msgstr "" +"Las interfaces de contrato definen la estructura y el comportamiento de un " +"contrato y sirven como la ABI pública del contrato. Enumeran todas las " +"firmas de funciones que expone un contrato. Para obtener una explicación " +"detallada de las interfaces, puede consultar el [Cairo Book](https://book." +"cairo-lang.org/ch99-01-02-a-simple-contract.html)." + +#: src/ch00/interacting/interfaces-traits.md:5 +msgid "" +"In cairo, to specify the interface you need to define a trait annotated with " +"`#[starknet::interface]` and then implement that trait in the contract." +msgstr "" +"En Cairo, para especificar la interfaz es necesario definir un trait anotado " +"con `#[starknet::interface]` y luego implementar ese trait en el contrato." + +#: src/ch00/interacting/interfaces-traits.md:7 +msgid "" +"When a function needs to access the contract state, it must have a `self` " +"parameter of type `ContractState`. This implies that the corresponding " +"function signature in the interface trait must also take a `TContractState` " +"type as a parameter. It's important to note that every function in the " +"contract interface must have this `self` parameter of type `TContractState`." +msgstr "" +"Cuando una función necesita acceder al estado del contrato, debe tener un " +"parámetro `self` de tipo `ContractState`. Esto implica que la firma de " +"función correspondiente en el trait de interfaz también debe tomar un tipo " +"`TContractState` como parámetro. Es importante tener en cuenta que todas las " +"funciones de la interfaz del contrato deben tener este parámetro `self` de " +"tipo `TContractState`." + +#: src/ch00/interacting/interfaces-traits.md:9 +msgid "" +"You can use the `#[generate_trait]` attribute to implicitly generate the " +"trait for a specific implementation block. This attribute automatically " +"generates a trait with the same functions as the ones in the implemented " +"block, replacing the `self` parameter with a generic `TContractState` " +"parameter. However, you will need to annotate the block with the " +"`#[abi(per_item)]` attribute, and each function with the appropriate " +"attribute depending on whether it's an external function, a constructor or a " +"l1 handler." +msgstr "" +"Puedes utilizar el atributo `#[generate_trait]` para generar implícitamente " +"el trait para un bloque de implementación específico. Este atributo genera " +"automáticamente un trait con las mismas funciones que las del bloque " +"implementado, sustituyendo el parámetro `self` por un parámetro genérico " +"`TContractState`. Sin embargo, tendrás que anotar el bloque con el atributo " +"`#[abi(per_item)]`, y cada función con el atributo apropiado dependiendo de " +"si es una función externa, un constructor o un manejador l1." + +#: src/ch00/interacting/interfaces-traits.md:11 +msgid "In summary, there's two ways to handle interfaces:" +msgstr "En resumen, hay dos formas de manejar las interfaces:" + +#: src/ch00/interacting/interfaces-traits.md:13 +msgid "Explicitly, by defining a trait annoted with `#[starknet::interface]`" +msgstr "" +"Explícitamente, definiendo un trait anotado con `#[starknet::interface]`" + +#: src/ch00/interacting/interfaces-traits.md:14 +msgid "" +"Implicitly, by using `#[generate_trait]` combined with the #" +"\\[abi(per_item)\\]\\` attributes, and annotating each function inside the " +"implementation block with the appropriate attribute." +msgstr "" +"Implícitamente, utilizando `#[generate_trait]` combinado con los atributos #" +"\\[abi(per_item)\\]\\`, y anotando cada función dentro del bloque de " +"implementación con el atributo apropiado." + +#: src/ch00/interacting/interfaces-traits.md:16 +msgid "Explicit interface" +msgstr "Interfaz explícita" + +#: src/ch00/interacting/interfaces-traits.md:45 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit." +"cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit." +"cairo)." + +#: src/ch00/interacting/interfaces-traits.md:47 +msgid "Implicit interface" +msgstr "Interfaz implícita" + +#: src/ch00/interacting/interfaces-traits.md:73 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit." +"cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit." +"cairo)." + +#: src/ch00/interacting/interfaces-traits.md:75 +msgid "" +"Note: You can import an implicitly generated contract interface with `use " +"contract::{GeneratedContractInterface}`. However, the `Dispatcher` will not " +"be generated automatically." +msgstr "" +"Nota: Puedes importar una interfaz de contrato generada implícitamente con " +"`use contract::{GeneratedContractInterface}`. Sin embargo, el `Dispatcher` " +"no se generará automáticamente." + +#: src/ch00/interacting/interfaces-traits.md:77 +msgid "Internal functions" +msgstr "Funciones internas" + +#: src/ch00/interacting/interfaces-traits.md:79 +msgid "" +"You can also use `#[generate_trait]` for your internal functions. Since this " +"trait is generated in the context of the contract, you can define pure " +"functions as well (functions without the `self` parameter)." +msgstr "" +"También puedes utilizar `#[generate_trait]` para tus funciones internas. " +"Como este trait se genera en el contexto del contrato, también puedes " +"definir funciones puras (funciones sin el parámetro `self`)." + +#: src/ch00/interacting/interfaces-traits.md:127 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/" +"implicit_internal.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/interfaces_traits/src/" +"implicit_internal.cairo)." + +#: src/ch00/interacting/calling_other_contracts.md:3 +msgid "There are two different ways to call other contracts in Cairo." +msgstr "Hay dos formas diferentes de llamar a otros contratos en Cairo." + +#: src/ch00/interacting/calling_other_contracts.md:5 +msgid "" +"The easiest way to call other contracts is by using the dispatcher of the " +"contract you want to call. You can read more about Dispatchers in the [Cairo " +"Book](https://book.cairo-lang.org/ch99-02-02-contract-dispatcher-library-" +"dispatcher-and-system-calls.html#contract-dispatcher)" +msgstr "" +"La forma más fácil de llamar a otros contratos es usando el dispatcher del " +"contrato que quieres llamar. Puedes leer más sobre los dispatcher en el " +"[Cairo Book](https://book.cairo-lang.org/ch99-02-02-contract-dispatcher-" +"library-dispatcher-and-system-calls.html#contract-dispatcher)" + +#: src/ch00/interacting/calling_other_contracts.md:8 +msgid "" +"The other way is to use the `starknet::call_contract_syscall` syscall " +"yourself. However, this method is not recommended." +msgstr "" +"La otra forma es utilizar la llamada al sistema `starknet::" +"call_contract_syscall`. Sin embargo, este método no es recomendable." + +#: src/ch00/interacting/calling_other_contracts.md:10 +msgid "" +"In order to call other contracts using dispatchers, you will need to define " +"the called contract's interface as a trait annotated with the `#[starknet::" +"interface]` attribute, and then import the `IContractDispatcher` and " +"`IContractDispatcherTrait` items in your contract." +msgstr "" +"Para llamar a otros contratos utilizando dispatchers, tendrás que definir la " +"interfaz del contrato llamado como un trait anotado con el atributo " +"`#[starknet::interface]`, y luego importar los elementos " +"`IContractDispatcher` e `IContractDispatcherTrait` en tu contrato." + +#: src/ch00/interacting/calling_other_contracts.md:34 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x015c3Bb6D0DE26b64FEAF9A8f4655CfADb5c128bF4510398972704ee12775DB1) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/calling_other_contracts/src/callee." +"cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x015c3Bb6D0DE26b64FEAF9A8f4655CfADb5c128bF4510398972704ee12775DB1) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/calling_other_contracts/src/callee." +"cairo)." + +#: src/ch00/interacting/calling_other_contracts.md:38 +msgid "" +"// We need to have the interface of the callee contract defined\n" +"// so that we can import the Dispatcher.\n" +msgstr "" +"// We need to have the interface of the callee contract defined\n" +"// so that we can import the Dispatcher.\n" + +#: src/ch00/interacting/calling_other_contracts.md:53 +msgid "// We import the Dispatcher of the called contract\n" +msgstr "// We import the Dispatcher of the called contract\n" + +#: src/ch00/interacting/calling_other_contracts.md:68 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x05fa8aF796343d2f22c53C17149386b67B7AC4aB52D9e308Aa507C185aA44778) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/calling_other_contracts/src/caller." +"cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x05fa8aF796343d2f22c53C17149386b67B7AC4aB52D9e308Aa507C185aA44778) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/calling_other_contracts/src/caller." +"cairo)." + +#: src/ch00/interacting/factory.md:1 +msgid "Factory Pattern" +msgstr "Patrón de la Factory" + +#: src/ch00/interacting/factory.md:3 +msgid "" +"The factory pattern is a well known pattern in object oriented programming. " +"It provides an abstraction on how to instantiate a class. " +msgstr "" +"El patrón de factory es un patrón bien conocido en la programación orientada " +"a objetos. Proporciona una abstracción sobre cómo instanciar una clase. " + +#: src/ch00/interacting/factory.md:5 +msgid "" +"In the case of smart contracts, we can use this pattern by defining a " +"factory contract that have the sole responsibility of creating and managing " +"other contracts." +msgstr "" +"En el caso de los smart contracts, podemos utilizar este patrón definiendo " +"un contrato de factory que tenga la responsabilidad exclusiva de crear y " +"gestionar otros contratos." + +#: src/ch00/interacting/factory.md:7 +msgid "Class hash and contract instance" +msgstr "Clase hash e instancia de contrato" + +#: src/ch00/interacting/factory.md:9 +msgid "" +"In Starknet, there's a separation between contract's classes and instances. " +"A contract class serves as a blueprint, defined by the underling Cairo " +"bytecode, contract's entrypoints, ABI and Sierra program hash. The contract " +"class is identified by a class hash. When you want to add a new class to the " +"network, you first need to declare it." +msgstr "" +"En Starknet, hay una separación entre las clases de contrato y las " +"instancias. Una clase de contrato sirve como plano, definido por el código " +"de bytes subyacente de Cairo, los puntos de entrada del contrato, la ABI y " +"el hash del programa Sierra. La clase del contrato es identificada por un " +"hash de clase. Cuando se desea agregar una nueva clase a la red, primero es " +"necesario declararla." + +#: src/ch00/interacting/factory.md:11 +msgid "" +"When deploying a contract, you need to specify the class hash of the " +"contract you want to deploy. Each instance of a contract has their own " +"storage regardless of the class hash." +msgstr "" +"Cuando se despliega un contrato, es necesario especificar el hash de clase " +"del contrato que se desea desplegar. Cada instancia de un contrato tiene su " +"propio almacenamiento independientemente del hash de clase." + +#: src/ch00/interacting/factory.md:13 +msgid "" +"Using the factory pattern, we can deploy multiple instances of the same " +"contract class and handle upgrades easily." +msgstr "" +"Utilizando el patrón de factory, podemos desplegar múltiples instancias de " +"la misma clase de contrato y manejar las actualizaciones fácilmente." + +#: src/ch00/interacting/factory.md:15 +msgid "Minimal example" +msgstr "Ejemplo mínimo" + +#: src/ch00/interacting/factory.md:17 +msgid "" +"Here's a minimal example of a factory contract that deploy the " +"`SimpleCounter` contract:" +msgstr "" +"He aquí un ejemplo mínimo de un contrato de factory que despliega el " +"contrato `SimpleCounter`:" + +#: src/ch00/interacting/factory.md:24 +msgid "/// Create a new counter contract from stored arguments\n" +msgstr "/// Create a new counter contract from stored arguments\n" + +#: src/ch00/interacting/factory.md:27 +msgid "/// Create a new counter contract from the given arguments\n" +msgstr "/// Create a new counter contract from the given arguments\n" + +#: src/ch00/interacting/factory.md:30 +msgid "/// Update the argument\n" +msgstr "/// Update the argument\n" + +#: src/ch00/interacting/factory.md:33 +msgid "" +"/// Update the class hash of the Counter contract to deploy when creating a " +"new counter\n" +msgstr "" +"/// Update the class hash of the Counter contract to deploy when creating a " +"new counter\n" + +#: src/ch00/interacting/factory.md:44 +msgid "/// Store the constructor arguments of the contract to deploy\n" +msgstr "/// Store the constructor arguments of the contract to deploy\n" + +#: src/ch00/interacting/factory.md:46 +msgid "/// Store the class hash of the contract to deploy\n" +msgstr "/// Store the class hash of the contract to deploy\n" + +#: src/ch00/interacting/factory.md:59 +msgid "// Contructor arguments\n" +msgstr "// Contructor arguments\n" + +#: src/ch00/interacting/factory.md:62 +msgid "// Contract deployment\n" +msgstr "// Contract deployment\n" + +#: src/ch00/interacting/factory.md:88 +msgid "" +"This factory can be used to deploy multiple instances of the `SimpleCounter` " +"contract by calling the `create_counter` and `create_counter_at` functions." +msgstr "" +"Esta fábrica se puede utilizar para desplegar múltiples instancias del " +"contrato `SimpleCounter` llamando a las funciones `create_counter` y " +"`create_counter_at`." + +#: src/ch00/interacting/factory.md:90 +msgid "" +"The `SimpleCounter` class hash is stored inside the factory, and can be " +"upgraded with the `update_counter_class_hash` function which allows to reuse " +"the same factory contract when the `SimpleCounter` contract is upgraded." +msgstr "" +"El hash de la clase `SimpleCounter` se almacena dentro de la fábrica, y se " +"puede actualizar con la función `update_counter_class_hash` que permite " +"reutilizar el mismo contrato de fábrica cuando se actualiza el contrato " +"`SimpleCounter`." + +#: src/ch00/interacting/factory.md:92 +msgid "" +"This minimal example lacks several useful features such as access control, " +"tracking of deployed contracts, events, ..." +msgstr "" +"Este ejemplo mínimo carece de varias funciones útiles, como el control de " +"acceso, el seguimiento de los contratos desplegados, los eventos, ..." + +#: src/ch00/testing/contract-testing.md:1 +msgid "Contract Testing" +msgstr "Testing de Contrato" + +#: src/ch00/testing/contract-testing.md:3 +msgid "" +"Testing plays a crucial role in software development, especially for smart " +"contracts. In this section, we'll guide you through the basics of testing a " +"smart contract on Starknet with `scarb`." +msgstr "" +"Las pruebas juegan un papel crucial en el desarrollo de software, " +"especialmente para los smart contracts. En esta sección, te guiaremos a " +"través de los conceptos básicos de las pruebas de un smart contracts en " +"Starknet con `scarb`." + +#: src/ch00/testing/contract-testing.md:5 +msgid "Let's start with a simple smart contract as an example:" +msgstr "Empecemos con un simple contrato inteligente como ejemplo:" + +#: src/ch00/testing/contract-testing.md:50 +msgid "Now, take a look at the tests for this contract:" +msgstr "Ahora, eche un vistazo a las pruebas de este contrato:" + +#: src/ch00/testing/contract-testing.md:54 +msgid "" +"// Import the interface and dispatcher to be able to interact with the " +"contract.\n" +msgstr "" +"// Import the interface and dispatcher to be able to interact with the " +"contract.\n" + +#: src/ch00/testing/contract-testing.md:59 +msgid "// Import the deploy syscall to be able to deploy the contract.\n" +msgstr "// Import the deploy syscall to be able to deploy the contract.\n" + +#: src/ch00/testing/contract-testing.md:66 +msgid "// Use starknet test utils to fake the transaction context.\n" +msgstr "// Use starknet test utils to fake the transaction context.\n" + +#: src/ch00/testing/contract-testing.md:69 +msgid "// Deploy the contract and return its dispatcher.\n" +msgstr "// Deploy the contract and return its dispatcher.\n" + +#: src/ch00/testing/contract-testing.md:71 +msgid "// Set up constructor arguments.\n" +msgstr "// Set up constructor arguments.\n" + +#: src/ch00/testing/contract-testing.md:75 +msgid "// Declare and deploy\n" +msgstr "// Declare and deploy\n" + +#: src/ch00/testing/contract-testing.md:81 +msgid "" +"// Return the dispatcher.\n" +" // The dispatcher allows to interact with the contract based on its " +"interface.\n" +msgstr "" +"// Return the dispatcher.\n" +" // The dispatcher allows to interact with the contract based on its " +"interface.\n" + +#: src/ch00/testing/contract-testing.md:99 +msgid "// Fake the caller address to address 1\n" +msgstr "// Fake the caller address to address 1\n" + +#: src/ch00/testing/contract-testing.md:106 +msgid "// Fake the contract address to address 1\n" +msgstr "// Fake the contract address to address 1\n" + +#: src/ch00/testing/contract-testing.md:132 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/testing/src/lib.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch00-getting-started/testing/src/lib.cairo)." + +#: src/ch00/testing/contract-testing.md:134 +msgid "" +"To define our test, we use scarb, which allows us to create a separate " +"module guarded with `#[cfg(test)]`. This ensures that the test module is " +"only compiled when running tests using `scarb test`." +msgstr "" +"Para definir nuestro test, usamos scarb, que nos permite crear un módulo " +"separado protegido con `#[cfg(test)]`. Esto asegura que el módulo de prueba " +"sólo se compila cuando se ejecutan pruebas utilizando `scarb test`." + +#: src/ch00/testing/contract-testing.md:136 +msgid "" +"Each test is defined as a function with the `#[test]` attribute. You can " +"also check if a test panics using the `#[should_panic]` attribute." +msgstr "" +"Cada prueba se define como una función con el atributo `#[test]`. También " +"puede comprobar si una prueba entra en pánico utilizando el atributo " +"`#[should_panic]`." + +#: src/ch00/testing/contract-testing.md:138 +msgid "" +"As we are in the context of a smart contract, it's essential to set up the " +"gas limit. You do this by using the `#[available_gas(X)]` attribute to " +"specify the gas limit for a test. This is also a great way to ensure that " +"your contract's features stay under a certain gas limit!" +msgstr "" +"Como estamos en el contexto de un smart contract, es esencial establecer el " +"límite de gas. Esto se hace utilizando el atributo `#[available_gas(X)]` " +"para especificar el límite de gas para una prueba. ¡Esta es también una gran " +"manera de asegurar que las funciones de tu contrato se mantienen por debajo " +"de un cierto límite de gas!" + +#: src/ch00/testing/contract-testing.md:140 +msgid "Note: The term \"gas\" here refers to Sierra gas, not L1 gas" +msgstr "Nota: El término \"gas\" se refiere aquí al gas Sierra, no al gas L1" + +#: src/ch00/testing/contract-testing.md:142 +msgid "Now, let's move on to the testing process:" +msgstr "Pasemos ahora al proceso de prueba:" + +#: src/ch00/testing/contract-testing.md:143 +msgid "Use the `deploy` function logic to declare and deploy your contract." +msgstr "" +"Utilice la lógica de la función `deploy` para declarar y desplegar su " +"contrato." + +#: src/ch00/testing/contract-testing.md:144 +msgid "" +"Use `assert` to verify that the contract behaves as expected in the given " +"context." +msgstr "" +"Utilice `assert` para verificar que el contrato se comporta como se espera " +"en el contexto dado." + +#: src/ch00/testing/contract-testing.md:146 +msgid "" +"To make testing more convenient, the `testing` module of the corelib " +"provides some helpful functions:" +msgstr "" +"Para que las pruebas resulten más cómodas, el módulo `testing` de corelib " +"proporciona algunas funciones útiles:" + +#: src/ch00/testing/contract-testing.md:147 +msgid "`set_caller_address(address: ContractAddress)`" +msgstr "`set_caller_address(address: ContractAddress)`" + +#: src/ch00/testing/contract-testing.md:148 +msgid "`set_contract_address(address: ContractAddress)`" +msgstr "`set_contract_address(address: ContractAddress)`" + +#: src/ch00/testing/contract-testing.md:149 +msgid "`set_block_number(block_number: u64)`" +msgstr "`set_block_number(block_number: u64)`" + +#: src/ch00/testing/contract-testing.md:150 +msgid "`set_block_timestamp(block_timestamp: u64)`" +msgstr "`set_block_timestamp(block_timestamp: u64)`" + +#: src/ch00/testing/contract-testing.md:151 +msgid "`set_account_contract_address(address: ContractAddress)`" +msgstr "`set_account_contract_address(address: ContractAddress)`" + +#: src/ch00/testing/contract-testing.md:152 +msgid "`set_max_fee(fee: u128)`" +msgstr "`set_max_fee(fee: u128)`" + +#: src/ch00/testing/contract-testing.md:154 +msgid "" +"You may also need the `info` module from the corelib, which allows you to " +"access information about the current transaction context:" +msgstr "" +"También puede necesitar el módulo `info` de corelib, que le permite acceder " +"a información sobre el contexto de la transacción actual:" + +#: src/ch00/testing/contract-testing.md:155 +msgid "`get_caller_address() -> ContractAddress`" +msgstr "`get_caller_address() -> ContractAddress`" + +#: src/ch00/testing/contract-testing.md:156 +msgid "`get_contract_address() -> ContractAddress`" +msgstr "`get_contract_address() -> ContractAddress`" + +#: src/ch00/testing/contract-testing.md:157 +msgid "`get_block_info() -> Box`" +msgstr "`get_block_info() -> Box`" + +#: src/ch00/testing/contract-testing.md:158 +msgid "`get_tx_info() -> Box`" +msgstr "`get_tx_info() -> Box`" + +#: src/ch00/testing/contract-testing.md:159 +msgid "`get_block_timestamp() -> u64`" +msgstr "`get_block_timestamp() -> u64`" + +#: src/ch00/testing/contract-testing.md:160 +msgid "`get_block_number() -> u64`" +msgstr "`get_block_number() -> u64`" + +#: src/ch00/testing/contract-testing.md:163 +msgid "" +"You can found the full list of functions in the [Starknet Corelib repo]" +"(https://github.com/starkware-libs/cairo/tree/main/corelib/src/starknet). " +"You can also find a detailled explaination of testing in cairo in the [Cairo " +"book - Chapter 8](https://book.cairo-lang.org/ch08-01-how-to-write-tests." +"html)." +msgstr "" +"Puedes encontrar la lista completa de funciones en [Starknet Corelib repo]" +"(https://github.com/starkware-libs/cairo/tree/main/corelib/src/starknet). " +"También puedes encontrar una explicación detallada de las pruebas en cairo " +"en el [Cairo book - Chapter 8](https://book.cairo-lang.org/ch08-01-how-to-" +"write-tests.html)." + +#: src/ch00/testing/contract-testing.md:166 +msgid "Starknet Foundry" +msgstr "Starknet Foundry" + +#: src/ch00/testing/contract-testing.md:170 +msgid "" +"Starknet Foundry is a powerful toolkit for developing smart contracts on " +"Starknet. It offers support for testing Starknet smart contracts on top of " +"`scarb` with the `Forge` tool." +msgstr "" +"Starknet Foundry es un potente conjunto de herramientas para el desarrollo " +"de contratos inteligentes en Starknet. Ofrece soporte para probar contratos " +"inteligentes Starknet sobre `scarb` con la herramienta `Forge`." + +#: src/ch00/testing/contract-testing.md:172 +msgid "" +"Testing with `snforge` is similar to the process we just described but " +"simplified. Moreover, additional features are on the way, including " +"cheatcodes or parallel tests execution. We highly recommend exploring " +"Starknet Foundry and incorporating it into your projects." +msgstr "" +"Probar con `snforge` es similar al proceso que acabamos de describir, pero " +"simplificado. Además, hay características adicionales en camino, incluyendo " +"cheatcodes o ejecución de pruebas en paralelo. Recomendamos encarecidamente " +"explorar Starknet Foundry e incorporarlo a tus proyectos." + +#: src/ch00/testing/contract-testing.md:174 +msgid "" +"For more detailed information about testing contracts with Starknet Foundry, " +"check out the [Starknet Foundry Book - Testing Contracts](https://foundry-rs." +"github.io/starknet-foundry/testing/contracts.html)." +msgstr "" +"Si desea información más detallada sobre los contratos de pruebas con " +"Starknet Foundry, consulte el [Starknet Foundry Book - Testing Contracts]" +"(https://foundry-rs.github.io/starknet-foundry/testing/contracts.html)." + +#: src/ch00/cairo_cheatsheet/cairo_cheatsheet.md:1 +msgid "Cairo Cheatsheet" +msgstr "Hoja de ruta de Cairo" + +#: src/ch00/cairo_cheatsheet/cairo_cheatsheet.md:3 +msgid "" +"This chapter aims to provide a quick reference for the most common Cairo " +"constructs." +msgstr "" +"Este capítulo pretende ofrecer una referencia rápida para las construcciones " +"más comunes de Cairo." + +#: src/ch00/cairo_cheatsheet/felt.md:1 +msgid "Felt252" +msgstr "Felt252" + +#: src/ch00/cairo_cheatsheet/felt.md:3 +msgid "" +"Felt252 is a fundamental data type in Cairo from which all other data types " +"are derived. Felt252 can also be used to store short-string representations " +"with a maximum length of 31 characters." +msgstr "" +"Felt252 es un tipo de datos fundamental en Cairo del que derivan todos los " +"demás tipos de datos. Felt252 también puede utilizarse para almacenar " +"representaciones de cadenas cortas con una longitud máxima de 31 caracteres." + +#: src/ch00/cairo_cheatsheet/felt.md:6 src/ch00/cairo_cheatsheet/arrays.md:20 +#: src/ch02/hash-solidity-compatible.md:5 +msgid "For example:" +msgstr "Por ejemplo:" + +#: src/ch00/cairo_cheatsheet/mapping.md:1 +msgid "Mapping" +msgstr "Mapping" + +#: src/ch00/cairo_cheatsheet/mapping.md:3 +msgid "" +"The `LegacyMap` type can be used to represent a collection of key-value." +msgstr "" +"El tipo `LegacyMap` se puede utilizar para representar una colección de key-" +"value." + +#: src/ch00/cairo_cheatsheet/mapping.md:51 +msgid "" +"// for a 2D mapping its important to take note of the amount of brackets " +"being used.\n" +msgstr "" +"// for a 2D mapping its important to take note of the amount of brackets " +"being used.\n" + +#: src/ch00/cairo_cheatsheet/arrays.md:3 +msgid "" +"Arrays are collections of elements of the same type. The possible operations " +"on arrays are defined with the `array::ArrayTrait` of the corelib:" +msgstr "" +"Las Arrays son colecciones de elementos del mismo tipo. Las posibles " +"operaciones sobre arrays se definen con el `array::ArrayTrait` de la corelib:" + +#: src/ch00/cairo_cheatsheet/arrays.md:37 +msgid "// Returns true if an array is empty, then false if it isn't.\n" +msgstr "// Returns true if an array is empty, then false if it isn't.\n" + +#: src/ch00/cairo_cheatsheet/loop.md:3 +msgid "" +"A loop specifies a block of code that will run repetitively until a halting " +"condition is encountered. For example:" +msgstr "" +"Un bucle especifica un bloque de código que se ejecutará repetidamente hasta " +"que se encuentre una condición de parada. Por ejemplo:" + +#: src/ch00/cairo_cheatsheet/loop.md:9 +msgid "// Same as ~ while (i < 10) arr.append(i++);\n" +msgstr "// Same as ~ while (i < 10) arr.append(i++);\n" + +#: src/ch00/cairo_cheatsheet/match.md:3 +msgid "" +"The \"match\" expression in Cairo allows us to control the flow of our code " +"by comparing a felt data type or an enum against various patterns and then " +"running specific code based on the pattern that matches. For example:" +msgstr "" +"La expresión \"match\" en Cairo nos permite controlar el flujo de nuestro " +"código comparando un tipo de dato sentido o un enum contra varios patrones y " +"luego ejecutando código específico basado en el patrón que coincida. Por " +"ejemplo:" + +#: src/ch00/cairo_cheatsheet/tuples.md:3 +msgid "" +"Tuples is a data type to group a fixed number of items of potentially " +"different types into a single compound structure. Unlike arrays, tuples have " +"a set length and can contain elements of varying types. Once a tuple is " +"created, its size cannot change. For example:" +msgstr "" +"Las tuplas son un tipo de datos para agrupar un número fijo de elementos de " +"tipos potencialmente diferentes en una única estructura compuesta. A " +"diferencia de las matrices, las tuplas tienen una longitud fija y pueden " +"contener elementos de distintos tipos. Una vez creada una tupla, su tamaño " +"no puede variar. Por ejemplo:" + +#: src/ch00/cairo_cheatsheet/tuples.md:7 +msgid "\"0x000\"" +msgstr "\"0x000\"" + +#: src/ch00/cairo_cheatsheet/tuples.md:11 +msgid "// Create tuple\n" +msgstr "// Create tuple\n" + +#: src/ch00/cairo_cheatsheet/tuples.md:14 +msgid "// Access tuple\n" +msgstr "// Access tuple\n" + +#: src/ch00/cairo_cheatsheet/struct.md:3 +msgid "" +"A struct is a data type similar to tuple. Like tuples they can be used to " +"hold data of different types. For example:" +msgstr "" +"Una estructura es un tipo de datos similar a una tupla. Al igual que las " +"tuplas, pueden utilizarse para contener datos de distintos tipos. Por " +"ejemplo:" + +#: src/ch00/cairo_cheatsheet/struct.md:7 +msgid "" +"// With Store, you can store Data's structs in the storage part of " +"contracts.\n" +msgstr "" +"// With Store, you can store Data's structs in the storage part of " +"contracts.\n" + +#: src/ch00/cairo_cheatsheet/type_casting.md:3 +msgid "" +"Cairo supports the conversion from one scalar types to another by using the " +"into and try_into methods. `traits::Into` is used for conversion from a " +"smaller data type to a larger data type, while `traits::TryInto` is used " +"when converting from a larger to a smaller type that might not fit. For " +"example:" +msgstr "" +"Cairo soporta la conversión de un tipo escalar a otro usando los métodos " +"into y try_into. `traits::Into` se utiliza para la conversión de un tipo de " +"datos más pequeño a otro más grande, mientras que `traits::TryInto` se " +"utiliza cuando se convierte de un tipo más grande a otro más pequeño que " +"podría no caber. Por ejemplo:" + +#: src/ch00/cairo_cheatsheet/type_casting.md:11 +msgid "" +"// Since a u32 might not fit in a u8 and a u16, we need to use try_into,\n" +" // then unwrap the Option type thats returned.\n" +msgstr "" +"// Since a u32 might not fit in a u8 and a u16, we need to use try_into,\n" +" // then unwrap the Option type thats returned.\n" + +#: src/ch00/cairo_cheatsheet/type_casting.md:16 +msgid "" +"// since new_u32 is the of the same type (u32) as rand_number, we can " +"directly assign them,\n" +" // or use the .into() method.\n" +msgstr "" +"// since new_u32 is the of the same type (u32) as rand_number, we can " +"directly assign them,\n" +" // or use the .into() method.\n" + +#: src/ch00/cairo_cheatsheet/type_casting.md:20 +msgid "" +"// When typecasting from a smaller size to an equal or larger size we use " +"the .into() method.\n" +" // Note: u64 and u128 are larger than u32, so a u32 type will always fit " +"into them.\n" +msgstr "" +"// When typecasting from a smaller size to an equal or larger size we use " +"the .into() method.\n" +" // Note: u64 and u128 are larger than u32, so a u32 type will always fit " +"into them.\n" + +#: src/ch00/cairo_cheatsheet/type_casting.md:25 +msgid "" +"// Since a felt252 is smaller than a u256, we can use the into() method\n" +msgstr "" +"// Since a felt252 is smaller than a u256, we can use the into() method\n" + +#: src/ch00/cairo_cheatsheet/type_casting.md:29 +msgid "//note a usize is smaller than a felt so we use the try_into\n" +msgstr "//note a usize is smaller than a felt so we use the try_into\n" + +#: src/ch01/upgradeable_contract.md:3 +msgid "" +"In Starknet, contracts are divided into two parts: contract classes and " +"contract instances. This division follows a similar concept used in object-" +"oriented programming languages, where we distinguish between the definition " +"and implementation of objects." +msgstr "" +"En Starknet, los contratos se dividen en dos partes: clases de contratos e " +"instancias de contratos. Esta división sigue un concepto similar utilizado " +"en los lenguajes de programación orientados a objetos, en los que se " +"distingue entre la definición y la implementación de los objetos." + +#: src/ch01/upgradeable_contract.md:8 +msgid "" +"A contract class is the definition of a contract: it specifies how the " +"contract behaves. It contains essential information like the Cairo byte " +"code, hint information, entry point names, and everything that defines its " +"semantics unambiguously." +msgstr "" +"Una clase de contrato es la definición de un contrato: especifica cómo se " +"comporta el contrato. Contiene información esencial como el código de bytes " +"de El Cairo, información de hint, nombres de puntos de entrada y todo lo que " +"define su semántica sin ambigüedades." + +#: src/ch01/upgradeable_contract.md:13 +msgid "" +"To identify different contract classes, Starknet assigns a unique identifier " +"to each class: the class hash. A contract instance is a deployed contract " +"that corresponds to a specific contract class. Think of it as an instance of " +"an object in languages like Java." +msgstr "" +"Para identificar las diferentes clases de contratos, Starknet asigna un " +"identificador único a cada clase: el hash de la clase. Una instancia de " +"contrato es un contrato desplegado que corresponde a una clase de contrato " +"específica. Piense en ello como una instancia de un objeto en lenguajes como " +"Java." + +#: src/ch01/upgradeable_contract.md:18 +msgid "" +"Each class is identified by its class hash, which is analogous to a class " +"name in an object-oriented programming language. A contract instance is a " +"deployed contract corresponding to a class." +msgstr "" +"Cada clase se identifica por su hash de clase, que es análogo a un nombre de " +"clase en un lenguaje de programación orientado a objetos. Una instancia de " +"contrato es un contrato desplegado correspondiente a una clase." + +#: src/ch01/upgradeable_contract.md:20 +msgid "" +"You can upgrade a deployed contract to a newer version by calling the " +"`replace_class_syscall` function. By using this function, you can update the " +"class hash associated with a deployed contract, effectively upgrading its " +"implementation. However, this will not modify the contract's storage, so all " +"the data stored in the contract will remain the same." +msgstr "" +"Puedes actualizar un contrato desplegado a una versión más reciente llamando " +"a la función `replace_class_syscall`. Usando esta función, puedes actualizar " +"el hash de clase asociado con un contrato desplegado, actualizando " +"efectivamente su implementación. Sin embargo, esto no modificará el " +"almacenamiento del contrato, por lo que todos los datos almacenados en el " +"contrato seguirán siendo los mismos." + +#: src/ch01/upgradeable_contract.md:22 +msgid "" +"To illustrate this concept, let's consider an example with two contracts: " +"`UpgradeableContract_V0`, and `UpgradeableContract_V1`. Start by deploying " +"`UpgradeableContract_V0` as the initial version. Next, send a transaction " +"that invokes the `upgrade` function, with the class hash of " +"`UpgradeableContract_V1` as parameter to upgrade the class hash of the " +"deployed contract to the `UpgradeableContract_V1` one. Then, call the " +"`version` method on the contract to see that the contract was upgraded to " +"the V1 version." +msgstr "" +"Para ilustrar este concepto, consideremos un ejemplo con dos contratos: " +"Contrato Actualizable V0 y Contrato Actualizable V1. Comience desplegando " +"`UpgradeableContract_V0` como versión inicial. A continuación, envía una " +"transacción que invoque a la función `upgrade`, con el hash de clase del " +"`UpgradeableContract_V1` como parámetro para actualizar el hash de clase del " +"contrato desplegado al del `UpgradeableContract_V1`. Luego, llama al método " +"`version` en el contrato para ver que el contrato fue actualizado a la " +"versión V1." + +#: src/ch01/upgradeable_contract.md:68 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x005300003ade5d10447d941a42d48b7141074cd8bade2b16520684896a5090ea) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/upgradeable_contract/src/" +"upgradeable_contract_v0.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x005300003ade5d10447d941a42d48b7141074cd8bade2b16520684896a5090ea) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/upgradeable_contract/src/" +"upgradeable_contract_v0.cairo)." + +#: src/ch01/upgradeable_contract.md:114 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x017c86152badd1d665b9836571bd6b0a484f028748aa13d9b2d5d9c9192fafc6) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/upgradeable_contract/src/" +"upgradeable_contract_v1.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x017c86152badd1d665b9836571bd6b0a484f028748aa13d9b2d5d9c9192fafc6) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/upgradeable_contract/src/" +"upgradeable_contract_v1.cairo)." + +#: src/ch01/simple_vault.md:1 +msgid "Simple Defi Vault" +msgstr "Simple Defi Vault" + +#: src/ch01/simple_vault.md:3 +msgid "" +"This is the Cairo adaptation of the [Solidity by example Vault](https://" +"solidity-by-example.org/defi/vault/). Here's how it works:" +msgstr "" +"Se trata de la adaptación en Cario de la [Solidity by example Vault](https://" +"solidity-by-example.org/defi/vault/). Funciona de la siguiente manera:" + +#: src/ch01/simple_vault.md:6 +msgid "" +"When a user deposits a token, the contract calculates the amount of shares " +"to mint." +msgstr "" +"Cuando un usuario deposita un token, el contrato calcula la cantidad de " +"acciones a acuñar." + +#: src/ch01/simple_vault.md:8 +msgid "" +"When a user withdraws, the contract burns their shares, calculates the " +"yield, and withdraw both the yield and the initial amount of token deposited." +msgstr "" +"Cuando un usuario se retira, el contrato quema sus acciones, calcula el " +"rendimiento y retira tanto el rendimiento como la cantidad inicial de token " +"depositada." + +#: src/ch01/simple_vault.md:12 +msgid "" +"// In order to make contract calls within our Vault,\n" +"// we need to have the interface of the remote ERC20 contract defined to " +"import the Dispatcher.\n" +msgstr "" +"// In order to make contract calls within our Vault,\n" +"// we need to have the interface of the remote ERC20 contract defined to " +"import the Dispatcher.\n" + +#: src/ch01/simple_vault.md:68 +msgid "" +"// a = amount\n" +" // B = balance of token before deposit\n" +" // T = total supply\n" +" // s = shares to mint\n" +" //\n" +" // (T + s) / T = (a + B) / B \n" +" //\n" +" // s = aT / B\n" +msgstr "" +"// a = amount\n" +" // B = balance of token before deposit\n" +" // T = total supply\n" +" // s = shares to mint\n" +" //\n" +" // (T + s) / T = (a + B) / B \n" +" //\n" +" // s = aT / B\n" + +#: src/ch01/simple_vault.md:92 +msgid "" +"// a = amount\n" +" // B = balance of token before withdraw\n" +" // T = total supply\n" +" // s = shares to burn\n" +" //\n" +" // (T - s) / T = (B - a) / B \n" +" //\n" +" // a = sB / T\n" +msgstr "" +"// a = amount\n" +" // B = balance of token before withdraw\n" +" // T = total supply\n" +" // s = shares to burn\n" +" //\n" +" // (T - s) / T = (B - a) / B \n" +" //\n" +" // a = sB / T\n" + +#: src/ch01/simple_vault.md:113 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/simple_vault/src/simple_vault.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/simple_vault/src/simple_vault.cairo)." + +#: src/ch01/erc20.md:3 +msgid "" +"Contracts that follow the [ERC20 Standard](https://eips.ethereum.org/EIPS/" +"eip-20) are called ERC20 tokens. They are used to represent fungible assets." +msgstr "" +"Los contratos que siguen el [Standard ERC20](https://eips.ethereum.org/EIPS/" +"eip-20) se denominan tokens ERC20. Se utilizan para representar activos " +"fungibles." + +#: src/ch01/erc20.md:5 +msgid "" +"To create an ERC20 conctract, it must implement the following interface:" +msgstr "Para crear un contrato ERC20, debe implementar la siguiente interfaz:" + +#: src/ch01/erc20.md:33 +msgid "" +"In Starknet, function names should be written in _snake_case_. This is not " +"the case in Solidity, where function names are written in _camelCase_. The " +"Starknet ERC20 interface is therefore slightly different from the Solidity " +"ERC20 interface." +msgstr "" +"En Starknet, los nombres de las funciones deben escribirse en _snake_case_. " +"Este no es el caso en Solidity, donde los nombres de las funciones se " +"escriben en _camelCase_. Por lo tanto, la interfaz ERC20 de Starknet es " +"ligeramente diferente de la interfaz ERC20 de Solidity." + +#: src/ch01/erc20.md:36 +msgid "Here's an implementation of the ERC20 interface in Cairo:" +msgstr "He aquí una implementación de la interfaz ERC20 en Cairo:" + +#: src/ch01/erc20.md:207 +msgid "// What can go wrong here?\n" +msgstr "// What can go wrong here?\n" + +#: src/ch01/erc20.md:224 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/erc20/src/token.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/erc20/src/token.cairo)." + +#: src/ch01/erc20.md:226 +msgid "" +"There's several other implementations, such as the [Open Zeppelin](https://" +"docs.openzeppelin.com/contracts-cairo/0.7.0/erc20) or the [Cairo By Example]" +"(https://cairo-by-example.com/examples/erc20/) ones." +msgstr "" +"Existen otras implementaciones, como la [Open Zeppelin](https://docs." +"openzeppelin.com/contracts-cairo/0.7.0/erc20) o la [Cairo By Example]" +"(https://cairo-by-example.com/examples/erc20/)." + +#: src/ch01/constant-product-amm.md:3 +msgid "" +"This is the Cairo adaptation of the [Solidity by example Constant Product " +"AMM](https://solidity-by-example.org/defi/constant-product-amm/)." +msgstr "" +"Se trata de la adaptación cairota de la [Solidez por ejemplo Producto " +"Constante AMM](https://solidity-by-example.org/defi/constant-product-amm/)." + +#: src/ch01/constant-product-amm.md:32 +msgid "" +"// Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" +" // E.g. 3 = 0.3%\n" +msgstr "" +"// Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" +" // E.g. 3 = 0.3%\n" + +#: src/ch01/constant-product-amm.md:41 +msgid "// assert(fee <= 1000, 'fee > 1000');\n" +msgstr "// assert(fee <= 1000, 'fee > 1000');\n" + +#: src/ch01/constant-product-amm.md:107 +msgid "" +"// How much dy for dx?\n" +" // xy = k\n" +" // (x + dx)(y - dy) = k\n" +" // y - dy = k / (x + dx)\n" +" // y - k / (x + dx) = dy\n" +" // y - xy / (x + dx) = dy\n" +" // (yx + ydx - xy) / (x + dx) = dy\n" +" // ydx / (x + dx) = dy\n" +msgstr "" +"// How much dy for dx?\n" +" // xy = k\n" +" // (x + dx)(y - dy) = k\n" +" // y - dy = k / (x + dx)\n" +" // y - k / (x + dx) = dy\n" +" // y - xy / (x + dx) = dy\n" +" // (yx + ydx - xy) / (x + dx) = dy\n" +" // ydx / (x + dx) = dy\n" + +#: src/ch01/constant-product-amm.md:135 +msgid "" +"// How much dx, dy to add?\n" +" //\n" +" // xy = k\n" +" // (x + dx)(y + dy) = k'\n" +" //\n" +" // No price change, before and after adding liquidity\n" +" // x / y = (x + dx) / (y + dy)\n" +" //\n" +" // x(y + dy) = y(x + dx)\n" +" // x * dy = y * dx\n" +" //\n" +" // x / y = dx / dy\n" +" // dy = y / x * dx\n" +msgstr "" +"// How much dx, dy to add?\n" +" //\n" +" // xy = k\n" +" // (x + dx)(y + dy) = k'\n" +" //\n" +" // No price change, before and after adding liquidity\n" +" // x / y = (x + dx) / (y + dy)\n" +" //\n" +" // x(y + dy) = y(x + dx)\n" +" // x * dy = y * dx\n" +" //\n" +" // x / y = dx / dy\n" +" // dy = y / x * dx\n" + +#: src/ch01/constant-product-amm.md:154 +msgid "" +"// How much shares to mint?\n" +" //\n" +" // f(x, y) = value of liquidity\n" +" // We will define f(x, y) = sqrt(xy)\n" +" //\n" +" // L0 = f(x, y)\n" +" // L1 = f(x + dx, y + dy)\n" +" // T = total shares\n" +" // s = shares to mint\n" +" //\n" +" // Total shares should increase proportional to increase in " +"liquidity\n" +" // L1 / L0 = (T + s) / T\n" +" //\n" +" // L1 * T = L0 * (T + s)\n" +" //\n" +" // (L1 - L0) * T / L0 = s\n" +msgstr "" +"// How much shares to mint?\n" +" //\n" +" // f(x, y) = value of liquidity\n" +" // We will define f(x, y) = sqrt(xy)\n" +" //\n" +" // L0 = f(x, y)\n" +" // L1 = f(x + dx, y + dy)\n" +" // T = total shares\n" +" // s = shares to mint\n" +" //\n" +" // Total shares should increase proportional to increase in " +"liquidity\n" +" // L1 / L0 = (T + s) / T\n" +" //\n" +" // L1 * T = L0 * (T + s)\n" +" //\n" +" // (L1 - L0) * T / L0 = s\n" + +#: src/ch01/constant-product-amm.md:171 +msgid "" +"// Claim\n" +" // (L1 - L0) / L0 = dx / x = dy / y\n" +" //\n" +" // Proof\n" +" // --- Equation 1 ---\n" +" // (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / " +"sqrt(xy)\n" +" //\n" +" // dx / dy = x / y so replace dy = dx * y / x\n" +" //\n" +" // --- Equation 2 ---\n" +" // Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / " +"sqrt(xy)\n" +" //\n" +" // Multiply by sqrt(x) / sqrt(x)\n" +" // Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - sqrt(x^2y)) / " +"sqrt(x^2y)\n" +" // = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +"(sqrt(y)sqrt(x^2))\n" +" // sqrt(y) on top and bottom cancels out\n" +" //\n" +" // --- Equation 3 ---\n" +" // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +"(sqrt(x^2)\n" +" // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)\n" +" // = ((x + dx) - x) / x\n" +" // = dx / x\n" +" // Since dx / dy = x / y,\n" +" // dx / x = dy / y\n" +" //\n" +" // Finally\n" +" // (L1 - L0) / L0 = dx / x = dy / y\n" +msgstr "" +"// Claim\n" +" // (L1 - L0) / L0 = dx / x = dy / y\n" +" //\n" +" // Proof\n" +" // --- Equation 1 ---\n" +" // (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / " +"sqrt(xy)\n" +" //\n" +" // dx / dy = x / y so replace dy = dx * y / x\n" +" //\n" +" // --- Equation 2 ---\n" +" // Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / " +"sqrt(xy)\n" +" //\n" +" // Multiply by sqrt(x) / sqrt(x)\n" +" // Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - sqrt(x^2y)) / " +"sqrt(x^2y)\n" +" // = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +"(sqrt(y)sqrt(x^2))\n" +" // sqrt(y) on top and bottom cancels out\n" +" //\n" +" // --- Equation 3 ---\n" +" // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +"(sqrt(x^2)\n" +" // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)\n" +" // = ((x + dx) - x) / x\n" +" // = dx / x\n" +" // Since dx / dy = x / y,\n" +" // dx / x = dy / y\n" +" //\n" +" // Finally\n" +" // (L1 - L0) / L0 = dx / x = dy / y\n" + +#: src/ch01/constant-product-amm.md:221 +msgid "" +"// Claim\n" +" // dx, dy = amount of liquidity to remove\n" +" // dx = s / T * x\n" +" // dy = s / T * y\n" +" //\n" +" // Proof\n" +" // Let's find dx, dy such that\n" +" // v / L = s / T\n" +" //\n" +" // where\n" +" // v = f(dx, dy) = sqrt(dxdy)\n" +" // L = total liquidity = sqrt(xy)\n" +" // s = shares\n" +" // T = total supply\n" +" //\n" +" // --- Equation 1 ---\n" +" // v = s / T * L\n" +" // sqrt(dxdy) = s / T * sqrt(xy)\n" +" //\n" +" // Amount of liquidity to remove must not change price so\n" +" // dx / dy = x / y\n" +" //\n" +" // replace dy = dx * y / x\n" +" // sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)\n" +" //\n" +" // Divide both sides of Equation 1 with sqrt(y / x)\n" +" // dx = s / T * sqrt(xy) / sqrt(y / x)\n" +" // = s / T * sqrt(x^2) = s / T * x\n" +" //\n" +" // Likewise\n" +" // dy = s / T * y\n" +msgstr "" +"// Claim\n" +" // dx, dy = amount of liquidity to remove\n" +" // dx = s / T * x\n" +" // dy = s / T * y\n" +" //\n" +" // Proof\n" +" // Let's find dx, dy such that\n" +" // v / L = s / T\n" +" //\n" +" // where\n" +" // v = f(dx, dy) = sqrt(dxdy)\n" +" // L = total liquidity = sqrt(xy)\n" +" // s = shares\n" +" // T = total supply\n" +" //\n" +" // --- Equation 1 ---\n" +" // v = s / T * L\n" +" // sqrt(dxdy) = s / T * sqrt(xy)\n" +" //\n" +" // Amount of liquidity to remove must not change price so\n" +" // dx / dy = x / y\n" +" //\n" +" // replace dy = dx * y / x\n" +" // sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)\n" +" //\n" +" // Divide both sides of Equation 1 with sqrt(y / x)\n" +" // dx = s / T * sqrt(xy) / sqrt(y / x)\n" +" // = s / T * sqrt(x^2) = s / T * x\n" +" //\n" +" // Likewise\n" +" // dy = s / T * y\n" + +#: src/ch01/constant-product-amm.md:253 +msgid "" +"// bal0 >= reserve0\n" +" // bal1 >= reserve1\n" +msgstr "" +"// bal0 >= reserve0\n" +" // bal1 >= reserve1\n" + +#: src/ch01/constant-product-amm.md:274 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/constant_product_amm/src/" +"constant_product_amm.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch01-applications/constant_product_amm/src/" +"constant_product_amm.cairo)." + +#: src/ch02/write_to_any_slot.md:3 +msgid "" +"On Starknet, a contract's storage is a map with 2^251 slots, where each slot " +"is a felt which is initialized to 0. The address of storage variables is " +"computed at compile time using the formula: `storage variable address := " +"pedersen(keccak(variable name), keys)`. Interactions with storage variables " +"are commonly performed using the `self.var.read()` and `self.var.write()` " +"functions." +msgstr "" +"En Starknet, el almacenamiento de un contrato es un mapa con 2^251 ranuras, " +"donde cada ranura es un felt que se inicializa a 0. La dirección de las " +"variables de almacenamiento se calcula en tiempo de compilación utilizando " +"la fórmula: `storage variable address := pedersen(keccak(variable name), " +"keys)`. Las interacciones con las variables de almacenamiento se realizan " +"normalmente utilizando las funciones `self.var.read()` y `self.var.write()`." + +#: src/ch02/write_to_any_slot.md:6 +msgid "" +"Nevertheless, we can use the `storage_write_syscall` and " +"`storage_read_syscall` syscalls, to write to and read from any storage slot. " +"This is useful when writing to storage variables that are not known at " +"compile time, or to ensure that even if the contract is upgraded and the " +"computation method of storage variable addresses changes, they remain " +"accessible." +msgstr "" +"Sin embargo, podemos usar las llamadas al sistema `storage_write_syscall` y " +"`storage_read_syscall`, para escribir y leer desde cualquier ranura de " +"almacenamiento. Esto es útil cuando se escribe en variables de " +"almacenamiento que no se conocen en tiempo de compilación, o para asegurarse " +"de que incluso si el contrato se actualiza y el método de cálculo de las " +"direcciones de las variables de almacenamiento cambia, siguen siendo " +"accesibles." + +#: src/ch02/write_to_any_slot.md:9 +msgid "" +"In the following example, we use the Poseidon hash function to compute the " +"address of a storage variable. Poseidon is a ZK-friendly hash function that " +"is cheaper and faster than Pedersen, making it an excellent choice for " +"onchain computations. Once the address is computed, we use the storage " +"syscalls to interact with it." +msgstr "" +"En el siguiente ejemplo, utilizamos la función hash Poseidon para calcular " +"la dirección de una variable de almacenamiento. Poseidon es una función hash " +"compatible con ZK que es más barata y rápida que Pedersen, lo que la " +"convierte en una excelente elección para cálculos en cadena. Una vez " +"calculada la dirección, utilizamos las llamadas al sistema de almacenamiento " +"para interactuar con ella." + +#: src/ch02/write_to_any_slot.md:49 +msgid "" +"// By taking the 250 least significant bits of the hash output, we get a " +"valid 250bits storage address.\n" +msgstr "" +"// By taking the 250 least significant bits of the hash output, we get a " +"valid 250bits storage address.\n" + +#: src/ch02/write_to_any_slot.md:56 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x033943CB781A4E63C9dcE0A1A09eAa3b617AA43CC61637C08c043a67f3fe0087) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/write_to_any_slot/src/contract." +"cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x033943CB781A4E63C9dcE0A1A09eAa3b617AA43CC61637C08c043a67f3fe0087) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/write_to_any_slot/src/contract." +"cairo)." + +#: src/ch02/storing_arrays.md:3 +msgid "" +"On Starknet, complex values (e.g., tuples or structs), are stored in a " +"continuous segment starting from the address of the storage variable. There " +"is a 256 field elements limitation to the maximal size of a complex storage " +"value, meaning that to store arrays of more than 255 elements in storage, we " +"would need to split it into segments of size `n <= 255` and store these " +"segments in multiple storage addresses. There is currently no native support " +"for storing arrays in Cairo, so you will need to write your own " +"implementation of the `Store` trait for the type of array you wish to store." +msgstr "" +"En Starknet, los valores complejos (por ejemplo, tuplas o structs), se " +"almacenan en un segmento continuo a partir de la dirección de la variable de " +"almacenamiento. Hay una limitación de 256 elementos de campo para el tamaño " +"máximo de un valor de almacenamiento complejo, lo que significa que para " +"almacenar matrices de más de 255 elementos en el almacenamiento, " +"necesitaríamos dividirlo en segmentos de tamaño `n <= 255` y almacenar estos " +"segmentos en múltiples direcciones de almacenamiento. Actualmente no hay " +"soporte nativo para almacenar arrays en Cairo, por lo que necesitarás " +"escribir tu propia implementación del rasgo `Store` para el tipo de array " +"que desees almacenar." + +#: src/ch02/storing_arrays.md:5 +msgid "" +"Note: While storing arrays in storage is possible, it is not always " +"recommended, as the read and write operations can get very costly. For " +"example, reading an array of size `n` requires `n` storage reads, and " +"writing to an array of size `n` requires `n` storage writes. If you only " +"need to access a single element of the array at a time, it is recommended to " +"use a `LegacyMap` and store the length in another variable instead." +msgstr "" +"Nota: Aunque es posible almacenar arrays, no siempre es recomendable, ya que " +"las operaciones de lectura y escritura pueden resultar muy costosas. Por " +"ejemplo, leer un array de tamaño `n` requiere `n` lecturas de " +"almacenamiento, y escribir en un array de tamaño `n` requiere `n` escrituras " +"de almacenamiento. Si sólo necesitas acceder a un único elemento del array " +"cada vez, se recomienda utilizar un `LegacyMap` y almacenar la longitud en " +"otra variable." + +#: src/ch02/storing_arrays.md:7 +msgid "" +"The following example demonstrates how to write a simple implementation of " +"the `StorageAccess` trait for the `Array` type, allowing us to " +"store arrays of up to 255 `felt252` elements." +msgstr "" +"El siguiente ejemplo muestra cómo escribir una implementación sencilla del " +"rasgo `StorageAccess` para el tipo `Array`, permitiéndonos " +"almacenar arrays de hasta 255 elementos `felt252`." + +#: src/ch02/storing_arrays.md:26 +msgid "" +"// Read the stored array's length. If the length is superior to 255, the " +"read will fail.\n" +msgstr "" +"// Read the stored array's length. If the length is superior to 255, the " +"read will fail.\n" + +#: src/ch02/storing_arrays.md:31 +msgid "" +"// Sequentially read all stored elements and append them to the array.\n" +msgstr "" +"// Sequentially read all stored elements and append them to the array.\n" + +#: src/ch02/storing_arrays.md:43 +msgid "// Return the array.\n" +msgstr "// Return the array.\n" + +#: src/ch02/storing_arrays.md:50 +msgid "// // Store the length of the array in the first storage slot.\n" +msgstr "// // Store the length of the array in the first storage slot.\n" + +#: src/ch02/storing_arrays.md:55 +msgid "// Store the array elements sequentially\n" +msgstr "// Store the array elements sequentially\n" + +#: src/ch02/storing_arrays.md:73 +msgid "" +"You can then import this implementation in your contract and use it to store " +"arrays in storage:" +msgstr "" +"A continuación, puede importar esta implementación en su contrato y " +"utilizarla para almacenar arrays en el almacenamiento:" + +#: src/ch02/storing_arrays.md:103 +msgid "" +"Visit contract on [Voyager](https://goerli.voyager.online/" +"contract/0x008F8069a3Fcd7691Db46Dc3b6F9D2C0436f9200E861330957Fd780A3595da86) " +"or play with it in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)." +msgstr "" +"Visita el contrato en [Voyager](https://goerli.voyager.online/" +"contract/0x008F8069a3Fcd7691Db46Dc3b6F9D2C0436f9200E861330957Fd780A3595da86) " +"o juega con él en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)." + +#: src/ch02/struct-mapping-key.md:1 +msgid "Structs as mapping keys" +msgstr "Estructuras como mapping keys" + +#: src/ch02/struct-mapping-key.md:3 +msgid "" +"In order to use structs as mapping keys, you can use `#[derive(Hash)]` on " +"the struct definition. This will automatically generate a hash function for " +"the struct that can be used to represent the struct as a key in a " +"`LegacyMap`." +msgstr "" +"Para utilizar estructuras como mapping keys, puede utilizar " +"`#[derive(Hash)]` en la definición de la estructura. Esto generará " +"automáticamente una función hash para la estructura que se puede utilizar " +"para representar la estructura como una key en un `LegacyMap`." + +#: src/ch02/struct-mapping-key.md:5 +msgid "" +"Consider the following example in which we would like to use an object of " +"type `Pet` as a key in a `LegacyMap`. The `Pet` struct has three fields: " +"`name`, `age` and `owner`. We consider that the combination of these three " +"fields uniquely identifies a pet." +msgstr "" +"Consideremos el siguiente ejemplo en el que queremos utilizar un objeto de " +"tipo `Pet` como clave en un `LegacyMap`. La estructura `Pet` tiene tres " +"campos: `name`, `age` y `owner`. Consideramos que la combinación de estos " +"tres campos identifica de forma única a una mascota." + +#: src/ch02/struct-mapping-key.md:45 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/struct_as_mapping_key/src/contract." +"cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/struct_as_mapping_key/src/contract." +"cairo)." + +#: src/ch02/hash-solidity-compatible.md:3 +msgid "" +"This contract demonstrates Keccak hashing in Cairo to match Solidity's " +"keccak256. While both use Keccak, their endianness differs: Cairo is little-" +"endian, Solidity big-endian. The contract achieves compatibility by hashing " +"in big-endian using `keccak_u256s_be_inputs`, and reversing the bytes of the " +"result with `u128_byte_reverse`." +msgstr "" +"Este contrato demuestra el hashing Keccak en Cairo para que coincida con el " +"keccak256 de Solidity. Mientras que ambos usan Keccak, su endianness " +"difiere: Cairo es little-endian, Solidity big-endian. El contrato consigue " +"la compatibilidad haciendo hashing en big-endian usando " +"`keccak_u256s_be_inputs`, e invirtiendo los bytes del resultado con " +"`u128_byte_reverse`." + +#: src/ch02/hash-solidity-compatible.md:27 +msgid "// Split the hashed value into two 128-bit segments\n" +msgstr "// Split the hashed value into two 128-bit segments\n" + +#: src/ch02/hash-solidity-compatible.md:31 +msgid "// Reverse each 128-bit segment\n" +msgstr "// Reverse each 128-bit segment\n" + +#: src/ch02/hash-solidity-compatible.md:35 +msgid "// Reverse merge the reversed segments back into a u256 value\n" +msgstr "// Reverse merge the reversed segments back into a u256 value\n" + +#: src/ch02/hash-solidity-compatible.md:44 +msgid "" +"Play with the contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/hash_solidity_compatible/src/" +"contract.cairo)." +msgstr "" +"Juega con el contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/hash_solidity_compatible/src/" +"contract.cairo)." + +#: src/ch02/optimisations/optimisations.md:3 +msgid "A collection of optimisation patterns to save gas and steps." +msgstr "Una colección de patrones de optimización para ahorrar gas y pasos." + +#: src/ch02/optimisations/store_using_packing.md:1 +msgid "Storage optimisation" +msgstr "Optimización del Storage" + +#: src/ch02/optimisations/store_using_packing.md:3 +msgid "" +"A smart contract has a limited amount of **storage slots**. Each slot can " +"store a single `felt252` value. Writing to a storage slot has a cost, so we " +"want to use as few storage slots as possible." +msgstr "" +"Un smart contract tiene una cantidad limitada de **storage slots**. Cada " +"ranura puede almacenar un único valor `felt252`. Escribir en una ranura de " +"almacenamiento tiene un coste, por lo que queremos utilizar el menor número " +"posible de ranuras de almacenamiento." + +#: src/ch02/optimisations/store_using_packing.md:6 +msgid "" +"In Cairo, every type is derived from the `felt252` type, which uses 252 bits " +"to store a value. This design is quite simple, but it does have a drawback: " +"it is not storage efficient. For example, if we want to store a `u8` value, " +"we need to use an entire slot, even though we only need 8 bits." +msgstr "" +"En Cairo, cada tipo deriva del tipo `felt252`, que utiliza 252 bits para " +"almacenar un valor. Este diseño es bastante simple, pero tiene un " +"inconveniente: no es eficiente en almacenamiento. Por ejemplo, si queremos " +"almacenar un valor `u8`, necesitamos usar un slot entero, aunque sólo " +"necesitemos 8 bits." + +#: src/ch02/optimisations/store_using_packing.md:9 +msgid "Packing" +msgstr "Packing" + +#: src/ch02/optimisations/store_using_packing.md:11 +msgid "" +"When storing multiple values, we can use a technique called **packing**. " +"Packing is a technique that allows us to store multiple values in a single " +"felt value. This is done by using the bits of the felt value to store " +"multiple values." +msgstr "" +"Cuando almacenamos múltiples valores, podemos utilizar una técnica llamada " +"**packing**. El empaquetado es una técnica que nos permite almacenar " +"múltiples valores en un único valor de felt. Esto se hace utilizando los " +"bits del valor de felt para almacenar múltiples valores." + +#: src/ch02/optimisations/store_using_packing.md:13 +msgid "" +"For example, if we want to store two `u8` values, we can use the first 8 " +"bits of the felt value to store the first `u8` value, and the last 8 bits to " +"store the second `u8` value. This way, we can store two `u8` values in a " +"single felt value." +msgstr "" +"Por ejemplo, si queremos almacenar dos valores `u8`, podemos utilizar los " +"primeros 8 bits del valor de felt para almacenar el primer valor `u8`, y los " +"últimos 8 bits para almacenar el segundo valor `u8`. De esta forma, podemos " +"almacenar dos valores `u8` en un único valor de felt." + +#: src/ch02/optimisations/store_using_packing.md:15 +msgid "" +"Cairo provides a built-in store using packing that you can use with the " +"`StorePacking` trait." +msgstr "" +"Cairo proporciona un almacén incorporado que usa empaquetado que puedes usar " +"con el trait `StorePacking`." + +#: src/ch02/optimisations/store_using_packing.md:24 +msgid "" +"This allows to store the type `T` by first packing it into the type " +"`PackedT` with the `pack` function, and then storing the `PackedT` value " +"with it's `Store` implementation. When reading the value, we first retrieve " +"the `PackedT` value, and then unpack it into the type `T` using the `unpack` " +"function." +msgstr "" +"Esto permite almacenar el tipo `T` empaquetándolo primero en el tipo " +"`PackedT` con la función `pack`, y luego almacenando el valor `PackedT` con " +"su implementación `Store`. Al leer el valor, primero recuperamos el valor " +"`PackedT`, y luego lo desempaquetamos en el tipo `T` utilizando la función " +"`unpack`." + +#: src/ch02/optimisations/store_using_packing.md:26 +msgid "" +"Here's an example of storing a `Time` struct with two `u8` values using the " +"`StorePacking` trait:" +msgstr "" +"He aquí un ejemplo de almacenamiento de una estructura `Time` con dos " +"valores `u8` utilizando el trait `StorePacking`:" + +#: src/ch02/optimisations/store_using_packing.md:75 +msgid "" +"// This will call the pack method of the TimePackable trait\n" +" // and store the resulting felt252\n" +msgstr "" +"// This will call the pack method of the TimePackable trait\n" +" // and store the resulting felt252\n" + +#: src/ch02/optimisations/store_using_packing.md:80 +msgid "" +"// This will read the felt252 value from storage\n" +" // and return the result of the unpack method of the " +"TimePackable trait\n" +msgstr "" +"// This will read the felt252 value from storage\n" +" // and return the result of the unpack method of the " +"TimePackable trait\n" + +#: src/ch02/optimisations/store_using_packing.md:88 +msgid "" +"Play with this contract in [Remix](https://remix.ethereum.org/?" +"#activate=Starknet-cairo1-compiler&url=https://github.com/NethermindEth/" +"StarknetByExample/blob/main/listings/ch02-advanced-concepts/" +"store_using_packing/src/contract.cairo)." +msgstr "" +"Juega con este contrato en [Remix](https://remix.ethereum.org/?" +"#activate=Starknet-cairo1-compiler&url=https://github.com/NethermindEth/" +"StarknetByExample/blob/main/listings/ch02-advanced-concepts/" +"store_using_packing/src/contract.cairo)." + +#: src/ch02/list.md:3 +msgid "" +"By default, there is no list type supported in Cairo, but you can use " +"Alexandria. You can refer to the [Alexandria documentation](https://github." +"com/keep-starknet-strange/alexandria/tree/main/src/storage) for more details." +msgstr "" +"Por defecto, no hay ningún tipo de lista soportado en Cairo, pero puedes " +"usar Alexandria. Puede consultar la [documentación de Alexandria](https://" +"github.com/keep-starknet-strange/alexandria/tree/main/src/storage) para más " +"detalles." + +#: src/ch02/list.md:5 +msgid "What is `List`?" +msgstr "¿Qué es `List`?" + +#: src/ch02/list.md:7 +msgid "An ordered sequence of values that can be used in Starknet storage:" +msgstr "" +"Una secuencia ordenada de valores que puede utilizarse en el storage de " +"Starknet:" + +#: src/ch02/list.md:16 +msgid "Interface" +msgstr "Interface" + +#: src/ch02/list.md:30 +msgid "" +"`List` also implements `IndexView` so you can use the familiar bracket " +"notation to access its members:" +msgstr "" +"`List` también implementa `IndexView` para que puedas utilizar la notación " +"familiar de corchetes para acceder a sus miembros:" + +#: src/ch02/list.md:36 +msgid "" +"Note that unlike `get`, using this bracket notation panics when accessing an " +"out of bounds index." +msgstr "" +"Tenga en cuenta que, a diferencia de `get`, el uso de esta notación de " +"corchetes entra en pánico cuando se accede a un índice fuera de los límites." + +#: src/ch02/list.md:38 +msgid "Support for custom types" +msgstr "Compatibilidad con tipos personalizados" + +#: src/ch02/list.md:40 +msgid "" +"`List` supports most of the corelib types out of the box. If you want to " +"store a your own custom type in a `List`, it has to implement the `Store` " +"trait. You can have the compiler derive it for you using the " +"`#[derive(starknet::Store)]` attribute." +msgstr "" +"`List` soporta la mayoría de los tipos de corelib. Si quieres almacenar un " +"tipo personalizado en una `List`, tiene que implementar el trait `Store`. " +"Puedes hacer que el compilador lo derive por ti usando el atributo " +"`#[derive(starknet::Store)]`." + +#: src/ch02/list.md:42 +msgid "Caveats" +msgstr "Advertencias" + +#: src/ch02/list.md:44 +msgid "There are two idiosyncacies you should be aware of when using `List`" +msgstr "Hay dos particularidades que debe tener en cuenta al utilizar `List`" + +#: src/ch02/list.md:46 +msgid "" +"The `append` operation costs 2 storage writes - one for the value itself and " +"another one for updating the List's length" +msgstr "" +"La operación `append` cuesta 2 escrituras de storage - una para el valor en " +"sí y otra para actualizar la longitud de la Lista" + +#: src/ch02/list.md:47 +msgid "" +"Due to a compiler limitation, it is not possible to use mutating operations " +"with a single inline statement. For example, `self.amounts.read().append(42);" +"` will not work. You have to do it in 2 steps:" +msgstr "" +"Debido a una limitación del compilador, no es posible utilizar operaciones " +"de mutación con una única sentencia inline. Por ejemplo, `self.amounts." +"read().append(42);` no funcionará. Tienes que hacerlo en 2 pasos:" + +#: src/ch02/list.md:54 +msgid "Dependencies" +msgstr "Dependencias" + +#: src/ch02/list.md:56 +msgid "Update your project dependencies by in the `Scarb.toml` file:" +msgstr "Actualice las dependencias de su proyecto en el archivo `Scarb.toml`:" + +#: src/ch02/list.md:60 +msgid "\"https://github.com/keep-starknet-strange/alexandria.git\"" +msgstr "\"https://github.com/keep-starknet-strange/alexandria.git\"" + +#: src/ch02/list.md:63 +msgid "" +"For example, let's use `List` to create a contract that tracks a list of " +"amounts and tasks:" +msgstr "" +"Por ejemplo, utilicemos `List` para crear un contrato que realice el " +"seguimiento de una lista de importes y tareas:" diff --git a/po/messages.pot b/po/messages.pot index 4a7c875a..749a5ada 100644 --- a/po/messages.pot +++ b/po/messages.pot @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Starknet by Example\n" -"POT-Creation-Date: 2023-12-01T20:54:04+09:00\n" +"POT-Creation-Date: 2023-12-06T10:11:16Z\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -205,7 +205,7 @@ msgid "" msgstr "" #: src/starknet-by-example.md:9 -msgid "The current version of this book use `scarb 2.3.0`" +msgid "The current version of this book use `scarb 2.3.1`" msgstr "" #: src/starknet-by-example.md:11 @@ -623,8 +623,8 @@ msgid "" "// The `_read_value` function is outside the implementation that is marked " "as `#[abi(embed_v0)]`, so it's an _internal_ function\n" " // and can only be called from within the contract.\n" -" // It can modify the contract's state as it is passed as a " -"reference.\n" +" // However, it can't modify the contract's state is passed as a " +"snapshot: it is only a \"view\" function.\n" msgstr "" #: src/ch00/basics/visibility-mutability.md:73 @@ -932,47 +932,59 @@ msgid "In Cairo, you can add comments with `//`." msgstr "" #: src/ch00/basics/documentation.md:7 -msgid "Contract Interface:" +msgid "Best Practices:" msgstr "" #: src/ch00/basics/documentation.md:9 msgid "" +"Since Cairo 1, the community has adopted a [Rust-like documentation " +"style](https://doc.rust-lang.org/rust-by-example/meta/doc.html)." +msgstr "" + +#: src/ch00/basics/documentation.md:11 +msgid "Contract Interface:" +msgstr "" + +#: src/ch00/basics/documentation.md:13 +msgid "" "In smart contracts, you will often have a trait that defines the contract's " "interface (with `#[starknet::interface]`). This is the perfect place to " "include detailed documentation explaining the purpose and functionality of " "the contract entry points. You can follow this template:" msgstr "" -#: src/ch00/basics/documentation.md:15 +#: src/ch00/basics/documentation.md:19 msgid "" "/// High-level description of the function\n" " ///\n" " /// # Arguments\n" +" ///\n" " /// * `arg_1` - Description of the argument\n" " /// * `arg_n` - ...\n" " ///\n" " /// # Returns\n" +" ///\n" " /// High-level description of the return value\n" msgstr "" -#: src/ch00/basics/documentation.md:27 +#: src/ch00/basics/documentation.md:33 msgid "" "Keep in mind that this should not describe the implementation details of the " "function, but rather the high-level purpose and functionality of the " "contract from the perspective of a user." msgstr "" -#: src/ch00/basics/documentation.md:29 +#: src/ch00/basics/documentation.md:35 msgid "Implementation Details:" msgstr "" -#: src/ch00/basics/documentation.md:31 +#: src/ch00/basics/documentation.md:37 msgid "" "When writing the logic of the contract, you can add comments to describe the " "technical implementation details of the functions." msgstr "" -#: src/ch00/basics/documentation.md:33 +#: src/ch00/basics/documentation.md:39 msgid "" "Avoid over-commenting: Comments should provide additional value and clarity." msgstr "" diff --git a/po/zh-cn.po b/po/zh-cn.po index aedc9584..09ed2d4a 100644 --- a/po/zh-cn.po +++ b/po/zh-cn.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Starknet by Example\n" -"POT-Creation-Date: \n" +"POT-Creation-Date: 2023-12-06T08:37:01Z\n" "PO-Revision-Date: 2023-12-05 18:26+0900\n" "Last-Translator: StarknetAstro \n" "Language-Team: Language zh-cn\n" @@ -12,6 +12,10 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.4.1\n" +#: src/SUMMARY.md:1 +msgid "Summary" +msgstr "" + #: src/SUMMARY.md:3 msgid "Introduction" msgstr "介绍" @@ -24,19 +28,19 @@ msgstr "入门" msgid "Basics of a Starknet contract" msgstr "Starknet合约的基本内容" -#: src/SUMMARY.md:9 +#: src/SUMMARY.md:9 src/ch00/basics/storage.md:1 src/ch00/basics/variables.md:8 msgid "Storage" msgstr "存储" -#: src/SUMMARY.md:10 +#: src/SUMMARY.md:10 src/ch00/basics/constructor.md:1 msgid "Constructor" msgstr "构造函数" -#: src/SUMMARY.md:11 +#: src/SUMMARY.md:11 src/ch00/basics/variables.md:1 msgid "Variables" msgstr "变量" -#: src/SUMMARY.md:12 +#: src/SUMMARY.md:12 src/ch00/basics/visibility-mutability.md:1 msgid "Visibility and Mutability" msgstr "可见性和可变性" @@ -44,39 +48,39 @@ msgstr "可见性和可变性" msgid "Counter Example" msgstr "计数器示例" -#: src/SUMMARY.md:14 +#: src/SUMMARY.md:14 src/ch00/basics/mappings.md:1 msgid "Mappings" msgstr "映射" -#: src/SUMMARY.md:15 +#: src/SUMMARY.md:15 src/ch00/basics/errors.md:1 msgid "Errors" msgstr "错误" -#: src/SUMMARY.md:16 +#: src/SUMMARY.md:16 src/ch00/basics/events.md:1 msgid "Events" msgstr "事件" -#: src/SUMMARY.md:17 +#: src/SUMMARY.md:17 src/ch00/basics/storing-custom-types.md:1 msgid "Storing Custom Types" msgstr "存储自定义类型" -#: src/SUMMARY.md:18 +#: src/SUMMARY.md:18 src/ch00/basics/custom-types-in-entrypoints.md:1 msgid "Custom types in entrypoints" msgstr "入口点中的自定义类型" -#: src/SUMMARY.md:19 +#: src/SUMMARY.md:19 src/ch00/basics/documentation.md:1 msgid "Documentation" msgstr "文档" -#: src/SUMMARY.md:20 +#: src/SUMMARY.md:20 src/ch00/interacting/interacting.md:1 msgid "Deploy and interact with contracts" msgstr "部署合约并与合约交互" -#: src/SUMMARY.md:21 +#: src/SUMMARY.md:21 src/ch00/interacting/interfaces-traits.md:1 msgid "Contract interfaces and Traits generation" msgstr "合约接口和Trait生成" -#: src/SUMMARY.md:22 +#: src/SUMMARY.md:22 src/ch00/interacting/calling_other_contracts.md:1 msgid "Calling other contracts" msgstr "调用其他合约" @@ -100,27 +104,27 @@ msgstr "Felt" msgid "LegacyMap" msgstr "LegacyMap" -#: src/SUMMARY.md:28 +#: src/SUMMARY.md:28 src/ch00/cairo_cheatsheet/arrays.md:1 msgid "Arrays" msgstr "数组" -#: src/SUMMARY.md:29 +#: src/SUMMARY.md:29 src/ch00/cairo_cheatsheet/loop.md:1 msgid "Loop" msgstr "循环" -#: src/SUMMARY.md:30 +#: src/SUMMARY.md:30 src/ch00/cairo_cheatsheet/match.md:1 msgid "Match" msgstr "匹配" -#: src/SUMMARY.md:31 +#: src/SUMMARY.md:31 src/ch00/cairo_cheatsheet/tuples.md:1 msgid "Tuples" msgstr "元组" -#: src/SUMMARY.md:32 +#: src/SUMMARY.md:32 src/ch00/cairo_cheatsheet/struct.md:1 msgid "Struct" msgstr "结构体" -#: src/SUMMARY.md:33 +#: src/SUMMARY.md:33 src/ch00/cairo_cheatsheet/type_casting.md:1 msgid "Type casting" msgstr "类型转换" @@ -128,7 +132,7 @@ msgstr "类型转换" msgid "Applications examples" msgstr "应用实例" -#: src/SUMMARY.md:37 +#: src/SUMMARY.md:37 src/ch01/upgradeable_contract.md:1 msgid "Upgradeable Contract" msgstr "可升级合约" @@ -136,11 +140,11 @@ msgstr "可升级合约" msgid "Defi Vault" msgstr "Defi Vault" -#: src/SUMMARY.md:39 +#: src/SUMMARY.md:39 src/ch01/erc20.md:1 msgid "ERC20 Token" msgstr "ERC20 代币" -#: src/SUMMARY.md:40 +#: src/SUMMARY.md:40 src/ch01/constant-product-amm.md:1 msgid "Constant Product AMM" msgstr "恒定产品 AMM" @@ -148,11 +152,11 @@ msgstr "恒定产品 AMM" msgid "Advanced concepts" msgstr "高级概念" -#: src/SUMMARY.md:44 +#: src/SUMMARY.md:44 src/ch02/write_to_any_slot.md:1 msgid "Writing to any storage slot" msgstr "写入任何存储槽" -#: src/SUMMARY.md:45 +#: src/SUMMARY.md:45 src/ch02/storing_arrays.md:1 msgid "Storing Arrays" msgstr "存储数组" @@ -160,11 +164,11 @@ msgstr "存储数组" msgid "Struct as mapping key" msgstr "结构体作为映射键" -#: src/SUMMARY.md:47 +#: src/SUMMARY.md:47 src/ch02/hash-solidity-compatible.md:1 msgid "Hash Solidity Compatible" msgstr "兼容Hash Solidity" -#: src/SUMMARY.md:48 +#: src/SUMMARY.md:48 src/ch02/optimisations/optimisations.md:1 msgid "Optimisations" msgstr "优化" @@ -172,12 +176,13 @@ msgstr "优化" msgid "Storage Optimisations" msgstr "存储优化" -#: src/SUMMARY.md:50 +#: src/SUMMARY.md:50 src/ch02/list.md:1 msgid "List" msgstr "列表" #: src/starknet-by-example.md:1 -msgid "# Starknet by Example" +#, fuzzy +msgid "Starknet by Example" msgstr "# Starknet by Example" #: src/starknet-by-example.md:3 @@ -185,7 +190,8 @@ msgid "" "Starknet By Example is a collection of examples of how to use the Cairo " "programming language to create smart contracts on Starknet." msgstr "" -"Starknet By Example是如何使用Cairo编程语言在Starknet上创建智能合约的范例集。\n" +"Starknet By Example是如何使用Cairo编程语言在Starknet上创建智能合约的范例" +"集。\n" "中文版由 [StarknetAstro](https://twitter.com/StarkNetAstroCN) 社区翻译。" #: src/starknet-by-example.md:5 @@ -199,19 +205,20 @@ msgstr "" #: src/starknet-by-example.md:7 msgid "" -"Starknet smart contracts are written in the Cairo language. Cairo is a Turing-" -"complete programming language designed to write provable programs, " +"Starknet smart contracts are written in the Cairo language. Cairo is a " +"Turing-complete programming language designed to write provable programs, " "abstracting the zk-STARK proof system away from the programmer." msgstr "" -"Starknet智能合约是用Cairo语言编写的。Cairo语言是一种图灵完备的编程语言,旨在编" -"写可证明的程序,将 zk-STARK 证明系统从程序员手中抽象出来。" +"Starknet智能合约是用Cairo语言编写的。Cairo语言是一种图灵完备的编程语言,旨在" +"编写可证明的程序,将 zk-STARK 证明系统从程序员手中抽象出来。" #: src/starknet-by-example.md:9 msgid "The current version of this book use `scarb 2.3.1`" msgstr "本书当前版本使用 `scarb 2.3.1`" #: src/starknet-by-example.md:11 -msgid "## For whom is this for?" +#, fuzzy +msgid "For whom is this for?" msgstr "## 谁该读这本书?" #: src/starknet-by-example.md:13 @@ -220,32 +227,33 @@ msgid "" "smart contracts on Starknet using Cairo with some technical background in " "programming and blockchain." msgstr "" -"Starknet By Example适合想要快速学习如何使用 Cairo 在 Starknet 上编写智能合约," -"并具有一定编程和区块链技术背景的人。" +"Starknet By Example适合想要快速学习如何使用 Cairo 在 Starknet 上编写智能合" +"约,并具有一定编程和区块链技术背景的人。" #: src/starknet-by-example.md:15 +#, fuzzy msgid "" "The first chapters will give you a basic understanding of the Cairo " "programming language and how to write, deploy and use smart contracts on " -"Starknet.\n" -"The later chapters will cover more advanced topics and show you how to write " -"more complex smart contracts." +"Starknet. The later chapters will cover more advanced topics and show you " +"how to write more complex smart contracts." msgstr "" "前几章将让你基本了解Cairo编程语言,以及如何在Starknet编写、部署和使用智能合" "约。\n" "后面的章节将涉及更高级的主题,并向你展示如何编写更复杂的智能合约。" #: src/starknet-by-example.md:18 -msgid "## Further reading" +#, fuzzy +msgid "Further reading" msgstr "## 进一步阅读" #: src/starknet-by-example.md:20 +#, fuzzy msgid "" "If you want to learn more about the Cairo programming language, you can read " -"the [Cairo Book](https://book.cairo-lang.org).\n" -"If you want to learn more about Starknet, you can read the [Starknet " -"documentation](https://docs.starknet.io/) and the [Starknet Book](https://" -"book.starknet.io)." +"the [Cairo Book](https://book.cairo-lang.org). If you want to learn more " +"about Starknet, you can read the [Starknet documentation](https://docs." +"starknet.io/) and the [Starknet Book](https://book.starknet.io)." msgstr "" "如果你想进一步了解 Cairo 编程语言,可以阅读[Cairo Book](https://book.cairo-" "lang.org/zh-cn/index.html)。\n" @@ -258,81 +266,43 @@ msgstr "以下是您可能会用到的其他资源清单:" #: src/starknet-by-example.md:24 msgid "" -"- [Starklings](https://github.com/shramee/starklings-cairo1): An interactive " -"tutorial to get you up and running with Cairo v1 and Starknet \n" -"- [Cairopractice](https://cairopractice.com/): A blog with a series of " -"articles about Cairo and Starknet\n" -"- [Cairo by example](https://cairo-by-example.com/): An introduction to " -"Cairo, with simple examples" -msgstr "" -"- [Starklings](https://github.com/shramee/starklings-cairo1):让您使用 Cairo " -"v1 和Starknet互动的教程\n" -"- [Cairopractice](https://cairopractice.com/):关于Cairo和Starknet的一系列文章" -"的博客\n" -"- [Cairo by example](https://cairo-by-example.com/):Cairo 简介,附带简单示例" - -#: src/starknet-by-example.md:28 -#: src/ch00/interacting/calling_other_contracts.md:69 -#: src/ch00/cairo_cheatsheet/felt.md:15 src/ch00/cairo_cheatsheet/loop.md:23 -#: src/ch00/cairo_cheatsheet/tuples.md:18 -#: src/ch00/cairo_cheatsheet/type_casting.md:33 -msgid "
Last change: 2023-11-30
" -msgstr "
Last change: 2023-11-30
" +"[Starklings](https://github.com/shramee/starklings-cairo1): An interactive " +"tutorial to get you up and running with Cairo v1 and Starknet " +msgstr "" + +#: src/starknet-by-example.md:25 +msgid "" +"[Cairopractice](https://cairopractice.com/): A blog with a series of " +"articles about Cairo and Starknet" +msgstr "" + +#: src/starknet-by-example.md:26 +msgid "" +"[Cairo by example](https://cairo-by-example.com/): An introduction to Cairo, " +"with simple examples" +msgstr "" #: src/ch00/basics/introduction.md:1 -msgid "# Basics of Smart Contracts in Cairo" +#, fuzzy +msgid "Basics of Smart Contracts in Cairo" msgstr "# Cairo的智能合约基础知识" #: src/ch00/basics/introduction.md:3 msgid "" -"The following chapters will introduce you to Starknet smart contracts and how " -"to write them in Cairo." +"The following chapters will introduce you to Starknet smart contracts and " +"how to write them in Cairo." msgstr "以下章节将向你介绍Starknet智能合约以及如何用Cairo编写这些合约。" -#: src/ch00/basics/introduction.md:5 src/ch00/basics/constructor.md:27 -#: src/ch00/basics/mappings.md:46 src/ch00/basics/errors.md:139 -#: src/ch00/basics/events.md:68 src/ch00/basics/storing-custom-types.md:39 -#: src/ch00/basics/custom-types-in-entrypoints.md:39 -#: src/ch00/testing/contract-testing.md:176 src/ch01/upgradeable_contract.md:117 -#: src/ch01/simple_vault.md:114 src/ch02/write_to_any_slot.md:58 -#: src/ch02/storing_arrays.md:105 src/ch02/struct-mapping-key.md:46 -#: src/ch02/optimisations/optimisations.md:5 -#: src/ch02/optimisations/store_using_packing.md:90 -msgid "
Last change: 2023-10-12
" -msgstr "
Last change: 2023-10-12
" - -#: src/ch00/basics/storage.md:1 -msgid "# Storage" -msgstr "# 存储" - #: src/ch00/basics/storage.md:3 msgid "Here's the most minimal contract you can write in Cairo:" msgstr "这是您用Cairo能写的最简短的合约:" -#: src/ch00/basics/storage.md:5 -msgid "" -"```rust\n" -"#[starknet::contract]\n" -"mod Contract {\n" -" #[storage]\n" -" struct Storage {}\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::contract]\n" -"mod Contract {\n" -" #[storage]\n" -" struct Storage {}\n" -"}\n" -"```" - #: src/ch00/basics/storage.md:13 +#, fuzzy msgid "" "Storage is a struct annoted with `#[storage]`. Every contract must have one " -"and only one storage.\n" -"It's a key-value store, where each key will be mapped to a storage address of " -"the contract's storage space." +"and only one storage. It's a key-value store, where each key will be mapped " +"to a storage address of the contract's storage space." msgstr "" "存储是一个结构体,用 `#[storage]`标注。每个合约必须有且仅有一个存储空间。\n" "它是一个键值存储空间,其中每个键都将映射到合约存储空间的存储地址。" @@ -345,37 +315,12 @@ msgstr "" "您可以在合约中定义 [存储变量](./variables.md#storage-variables),然后使用它" "们来存储和检索数据。" -#: src/ch00/basics/storage.md:17 -msgid "" -"```rust\n" -"#[starknet::contract]\n" -"mod Contract {\n" -" #[storage]\n" -" struct Storage {\n" -" a: u128,\n" -" b: u8,\n" -" c: u256\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::contract]\n" -"mod Contract {\n" -" #[storage]\n" -" struct Storage {\n" -" a: u128,\n" -" b: u8,\n" -" c: u256\n" -" }\n" -"}\n" -"```" - #: src/ch00/basics/storage.md:29 +#, fuzzy msgid "" -"> Actually these two contracts have the same underlying sierra program.\n" -"> From the compiler's perspective, the storage variables don't exist until " -"they are used." +"Actually these two contracts have the same underlying sierra program. From " +"the compiler's perspective, the storage variables don't exist until they are " +"used." msgstr "" "> 实际上,这两个合约的底层 sierra 程序是一样的。\n" "> 从编译器的角度来看,存储变量在使用之前是不存在的。" @@ -385,15 +330,6 @@ msgid "" "You can also read about [storing custom types](./storing-custom-types.md)" msgstr "您还可以阅读有关 [存储自定义类型](./storing-custom-types.md) 的内容。" -#: src/ch00/basics/storage.md:34 src/ch00/basics/variables.md:126 -#: src/ch01/constant-product-amm.md:275 -msgid "
Last change: 2023-11-20
" -msgstr "
Last change: 2023-11-20
" - -#: src/ch00/basics/constructor.md:1 -msgid "# Constructor" -msgstr "# 构造函数" - #: src/ch00/basics/constructor.md:3 msgid "" "Constructors are a special type of function that runs only once when " @@ -402,59 +338,23 @@ msgid "" "constructor function must be annotated with the `#[constructor]` attribute. " "Also, a good practice consists in naming that function `constructor`." msgstr "" -"构造函数是一种特殊类型的函数,只在部署合约时运行一次,可用于初始化合约的状态。" -"你的合约不能有一个以上的构造函数,而且构造函数必须使用 `#[constructor]` 属性注" -"释。此外,一个好的做法是将该函数命名为 `constructor`。" +"构造函数是一种特殊类型的函数,只在部署合约时运行一次,可用于初始化合约的状" +"态。你的合约不能有一个以上的构造函数,而且构造函数必须使用 `#[constructor]` " +"属性注释。此外,一个好的做法是将该函数命名为 `constructor`。" #: src/ch00/basics/constructor.md:5 msgid "" "Here's a simple example that demonstrates how to initialize the state of a " "contract on deployment by defining logic inside a constructor." msgstr "" -"下面是一个简单的示例,演示如何通过在构造函数中定义逻辑,在部署时初始化合约的状" -"态。" +"下面是一个简单的示例,演示如何通过在构造函数中定义逻辑,在部署时初始化合约的" +"状态。" -#: src/ch00/basics/constructor.md:7 +#: src/ch00/basics/constructor.md:17 msgid "" -"```rust\n" -"#[starknet::contract]\n" -"mod ExampleConstructor {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" names: LegacyMap::,\n" -" }\n" -"\n" -" // The constructor is decorated with a `#[constructor]` attribute.\n" +"// The constructor is decorated with a `#[constructor]` attribute.\n" " // It is not inside an `impl` block.\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, name: felt252, address: " -"ContractAddress) {\n" -" self.names.write(address, name);\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::contract]\n" -"mod ExampleConstructor {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" names: LegacyMap::,\n" -" }\n" -"\n" -" // The constructor is decorated with a `#[constructor]` attribute.\n" -" // It is not inside an `impl` block.\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, name: felt252, address: " -"ContractAddress) {\n" -" self.names.write(address, name);\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/constructor.md:25 msgid "" @@ -471,48 +371,55 @@ msgstr "" "blob/main/listings/ch00-getting-started/constructor/src/constructor.cairo) 中" "尝试它。" -#: src/ch00/basics/variables.md:1 -msgid "# Variables" -msgstr "# 变量" - #: src/ch00/basics/variables.md:3 msgid "There are 3 types of variables in Cairo contracts:" msgstr "Cairo合约中有 3 种变量:" #: src/ch00/basics/variables.md:5 -msgid "" -"- Local\n" -" - declared inside a function\n" -" - not stored on the blockchain\n" -"- Storage\n" -" - declared in the [Storage](./storage.md) of a contract\n" -" - can be accessed from one execution to another\n" -"- Global\n" -" - provides information about the blockchain\n" -" - accessed anywhere, even within library functions" -msgstr "" -"- 局部\n" -" - 在函数中声明\n" -" - 不存储在区块链中\n" -"- 存储\n" -" - 在合约的 [Storage](./storage.md) 中声明\n" -" - 可从一个执行过程访问到另一个执行过程\n" -"- 全局\n" -" - 提供有关区块链的信息\n" -" - 可在任何地方访问,甚至在库函数中" +msgid "Local" +msgstr "" + +#: src/ch00/basics/variables.md:6 +msgid "declared inside a function" +msgstr "" + +#: src/ch00/basics/variables.md:7 +msgid "not stored on the blockchain" +msgstr "" + +#: src/ch00/basics/variables.md:9 +msgid "declared in the [Storage](./storage.md) of a contract" +msgstr "" + +#: src/ch00/basics/variables.md:10 +msgid "can be accessed from one execution to another" +msgstr "" + +#: src/ch00/basics/variables.md:11 +msgid "Global" +msgstr "" + +#: src/ch00/basics/variables.md:12 +msgid "provides information about the blockchain" +msgstr "" + +#: src/ch00/basics/variables.md:13 +msgid "accessed anywhere, even within library functions" +msgstr "" #: src/ch00/basics/variables.md:15 -msgid "## Local Variables" +#, fuzzy +msgid "Local Variables" msgstr "## 局部变量" #: src/ch00/basics/variables.md:17 msgid "" -"Local variables are used and accessed within the scope of a specific function " -"or block of code. They are temporary and exist only for the duration of that " -"particular function or block execution." +"Local variables are used and accessed within the scope of a specific " +"function or block of code. They are temporary and exist only for the " +"duration of that particular function or block execution." msgstr "" -"局部变量在特定函数或代码块的范围内使用和访问。它们是临时的,只在特定函数或代码" -"块执行期间存在。" +"局部变量在特定函数或代码块的范围内使用和访问。它们是临时的,只在特定函数或代" +"码块执行期间存在。" #: src/ch00/basics/variables.md:19 msgid "" @@ -522,77 +429,25 @@ msgid "" "a specific context. They also make the code more readable by giving names to " "intermediate values." msgstr "" -"局部变量存储在内存中,不会存储在区块链上。这就意味着在执行过程中无法访问它们。" -"局部变量可用于存储仅在特定上下文中相关的临时数据。通过为中间值命名,它们还能使" -"代码更具可读性。" +"局部变量存储在内存中,不会存储在区块链上。这就意味着在执行过程中无法访问它" +"们。局部变量可用于存储仅在特定上下文中相关的临时数据。通过为中间值命名,它们" +"还能使代码更具可读性。" #: src/ch00/basics/variables.md:21 msgid "Here's a simple example of a contract with only local variables:" msgstr "下面是一个只有局部变量的简单合约示例:" -#: src/ch00/basics/variables.md:23 +#: src/ch00/basics/variables.md:37 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ILocalVariablesExample {\n" -" fn do_something(self: @TContractState, value: u32) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod LocalVariablesExample {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl LocalVariablesExample of super::" -"ILocalVariablesExample {\n" -" fn do_something(self: @ContractState, value: u32) -> u32 {\n" -" // This variable is local to the current block. It can't be " -"accessed once it goes out of scope.\n" -" let increment = 10;\n" -"\n" -" {\n" -" // The scope of a code block allows for local variable " -"declaration\n" -" // We can access variables defined in higher scopes.\n" -" let sum = value + increment;\n" -" sum\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" +"// This variable is local to the current block. It can't be accessed once it " +"goes out of scope.\n" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ILocalVariablesExample {\n" -" fn do_something(self: @TContractState, value: u32) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod LocalVariablesExample {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl LocalVariablesExample of super::" -"ILocalVariablesExample {\n" -" fn do_something(self: @ContractState, value: u32) -> u32 {\n" -" // This variable is local to the current block. It can't be " -"accessed once it goes out of scope.\n" -" let increment = 10;\n" -"\n" -" {\n" -" // The scope of a code block allows for local variable " -"declaration\n" + +#: src/ch00/basics/variables.md:41 +msgid "" +"// The scope of a code block allows for local variable declaration\n" " // We can access variables defined in higher scopes.\n" -" let sum = value + increment;\n" -" sum\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" +msgstr "" #: src/ch00/basics/variables.md:50 msgid "" @@ -610,22 +465,23 @@ msgstr "" "中尝试它。" #: src/ch00/basics/variables.md:52 -msgid "## Storage Variables" +#, fuzzy +msgid "Storage Variables" msgstr "## 存储用变量" #: src/ch00/basics/variables.md:54 msgid "" "Storage variables are persistent data stored on the blockchain. They can be " -"accessed from one execution to another, allowing the contract to remember and " -"update information over time." +"accessed from one execution to another, allowing the contract to remember " +"and update information over time." msgstr "" -"存储变量是存储在区块链上的持久数据。它们可以在不同的执行过程中被访问,从而使合" -"约能够保存和更新信息。" +"存储变量是存储在区块链上的持久数据。它们可以在不同的执行过程中被访问,从而使" +"合约能够保存和更新信息。" #: src/ch00/basics/variables.md:56 msgid "" -"To write or update a storage variable, you need to interact with the contract " -"through an external entrypoint by sending a transaction." +"To write or update a storage variable, you need to interact with the " +"contract through an external entrypoint by sending a transaction." msgstr "要写入或更新存储变量,需要通过外部入口点发送交易与合约交互。" #: src/ch00/basics/variables.md:58 @@ -638,73 +494,25 @@ msgstr "另一方面,只需与节点交互,就可以免费读取状态变量 msgid "Here's a simple example of a contract with one storage variable:" msgstr "下面是一个带有一个存储变量的简单合约示例:" -#: src/ch00/basics/variables.md:62 +#: src/ch00/basics/variables.md:70 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStorageVariableExample {\n" -" fn set(ref self: TContractState, value: u32);\n" -" fn get(self: @TContractState) -> u32;\n" -"}\n" -"#[starknet::contract]\n" -"mod StorageVariablesExample {\n" -" // All storage variables are contained in a struct called Storage\n" +"// All storage variables are contained in a struct called Storage\n" " // annotated with the `#[storage]` attribute\n" -" #[storage]\n" -" struct Storage {\n" -" // Storage variable holding a number\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StorageVariablesExample of super::" -"IStorageVariableExample {\n" -" // Write to storage variables by sending a transaction that calls an " -"external function\n" -" fn set(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -"\n" -" // Read from storage variables without sending transactions\n" -" fn get(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStorageVariableExample {\n" -" fn set(ref self: TContractState, value: u32);\n" -" fn get(self: @TContractState) -> u32;\n" -"}\n" -"#[starknet::contract]\n" -"mod StorageVariablesExample {\n" -" // All storage variables are contained in a struct called Storage\n" -" // annotated with the `#[storage]` attribute\n" -" #[storage]\n" -" struct Storage {\n" -" // Storage variable holding a number\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StorageVariablesExample of super::" -"IStorageVariableExample {\n" -" // Write to storage variables by sending a transaction that calls an " + +#: src/ch00/basics/variables.md:74 +msgid "// Storage variable holding a number\n" +msgstr "" + +#: src/ch00/basics/variables.md:80 +msgid "" +"// Write to storage variables by sending a transaction that calls an " "external function\n" -" fn set(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -"\n" -" // Read from storage variables without sending transactions\n" -" fn get(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/ch00/basics/variables.md:85 +msgid "// Read from storage variables without sending transactions\n" +msgstr "" #: src/ch00/basics/variables.md:92 msgid "" @@ -723,17 +531,18 @@ msgstr "" "cairo) 中尝试它。" #: src/ch00/basics/variables.md:94 -msgid "## Global Variables" +#, fuzzy +msgid "Global Variables" msgstr "## 全局变量" #: src/ch00/basics/variables.md:96 msgid "" "Global variables are predefined variables that provide information about the " -"blockchain and the current execution environment. They can be accessed at any " -"time and from anywhere!" +"blockchain and the current execution environment. They can be accessed at " +"any time and from anywhere!" msgstr "" -"全局变量是预定义变量,可提供有关区块链和当前执行环境的信息。可以随时随地访问它" -"们!" +"全局变量是预定义变量,可提供有关区块链和当前执行环境的信息。可以随时随地访问" +"它们!" #: src/ch00/basics/variables.md:98 msgid "" @@ -748,60 +557,20 @@ msgid "" "caller of the current transaction, and the `get_contract_address` function " "returns the address of the current contract." msgstr "" -"例如,`get_caller_address`函数返回当前事务的调用者地址,`get_contract_address`" -"函数返回当前合同的地址。" +"例如,`get_caller_address`函数返回当前事务的调用者地址," +"`get_contract_address`函数返回当前合同的地址。" -#: src/ch00/basics/variables.md:102 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IGlobalExample {\n" -" fn foo(ref self: TContractState);\n" -"}\n" -"#[starknet::contract]\n" -"mod GlobalExample {\n" -" // import the required functions from the starknet core library\n" -" use starknet::get_caller_address;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl GlobalExampleImpl of super::IGlobalExample {\n" -" fn foo(ref self: ContractState) {\n" -" // Call the get_caller_address function to get the sender " -"address\n" -" let caller = get_caller_address();\n" -" // ...\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/ch00/basics/variables.md:109 +msgid "// import the required functions from the starknet core library\n" +msgstr "" + +#: src/ch00/basics/variables.md:118 +msgid "// Call the get_caller_address function to get the sender address\n" +msgstr "" + +#: src/ch00/basics/variables.md:120 +msgid "// ...\n" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IGlobalExample {\n" -" fn foo(ref self: TContractState);\n" -"}\n" -"#[starknet::contract]\n" -"mod GlobalExample {\n" -" // import the required functions from the starknet core library\n" -" use starknet::get_caller_address;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl GlobalExampleImpl of super::IGlobalExample {\n" -" fn foo(ref self: ContractState) {\n" -" // Call the get_caller_address function to get the sender " -"address\n" -" let caller = get_caller_address();\n" -" // ...\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/variables.md:125 msgid "" @@ -809,21 +578,19 @@ msgid "" "contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) " "or play with it in [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/variables/src/global_variables.cairo)." +"blob/main/listings/ch00-getting-started/variables/src/global_variables." +"cairo)." msgstr "" "访问 [Voyager](https://goerli.voyager.online/" "contract/0x05bD2F3943bd4e030f85678b55b2EC2C1be939e32388530FB20ED967B3Be433F) " "上的合约,或在 [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/variables/src/global_variables.cairo) " -"中尝试它。" - -#: src/ch00/basics/visibility-mutability.md:1 -msgid "# Visibility and Mutability" -msgstr "# 可见性和可变性" +"blob/main/listings/ch00-getting-started/variables/src/global_variables." +"cairo) 中尝试它。" #: src/ch00/basics/visibility-mutability.md:3 -msgid "## Visibility" +#, fuzzy +msgid "Visibility" msgstr "## 可见性" #: src/ch00/basics/visibility-mutability.md:5 @@ -831,9 +598,13 @@ msgid "There are two types of functions in Starknet contracts:" msgstr "Starknet合约有两种功能:" #: src/ch00/basics/visibility-mutability.md:7 +msgid "Functions that are accessible externally and can be called by anyone." +msgstr "" + +#: src/ch00/basics/visibility-mutability.md:8 +#, fuzzy msgid "" -"- Functions that are accessible externally and can be called by anyone.\n" -"- Functions that are only accessible internally and can only be called by " +"Functions that are only accessible internally and can only be called by " "other functions in the contract." msgstr "" "- 外部可访问、任何人都可调用的函数。\n" @@ -841,42 +612,53 @@ msgstr "" #: src/ch00/basics/visibility-mutability.md:10 msgid "" -"These functions are also typically divided into two different implementations " -"blocks. The first `impl` block for externally accessible functions is " -"explicitly annotated with an `#[abi(embed_v0)]` attribute. This indicates " -"that all the functions inside this block can be called either as a " +"These functions are also typically divided into two different " +"implementations blocks. The first `impl` block for externally accessible " +"functions is explicitly annotated with an `#[abi(embed_v0)]` attribute. This " +"indicates that all the functions inside this block can be called either as a " "transaction or as a view function. The second `impl` block for internally " "accessible functions is not annotated with any attribute, which means that " "all the functions inside this block are private by default." msgstr "" -"这些函数通常也分为两个不同的实现块。第一个`impl`块用于外部访问的函数,明确标注" -"了 `#[abi(embed_v0)]`属性。这表明该代码块中的所有函数都可以作为交易或视图函数" -"调用。第二个用于内部可访问函数的 `impl` 块没有注释任何属性,这意味着该块中的所" -"有函数默认都是私有的。" +"这些函数通常也分为两个不同的实现块。第一个`impl`块用于外部访问的函数,明确标" +"注了 `#[abi(embed_v0)]`属性。这表明该代码块中的所有函数都可以作为交易或视图函" +"数调用。第二个用于内部可访问函数的 `impl` 块没有注释任何属性,这意味着该块中" +"的所有函数默认都是私有的。" #: src/ch00/basics/visibility-mutability.md:12 -msgid "## State Mutability" +#, fuzzy +msgid "State Mutability" msgstr "## 状态可变性" #: src/ch00/basics/visibility-mutability.md:14 +#, fuzzy msgid "" "Regardless of whether a function is internal or external, it can either " "modify the contract's state or not. When we declare functions that interact " -"with storage variables inside a smart contract,\n" -"we need to explicitly state that we are accessing the `ContractState` by " -"adding it as the first parameter of the function. This can be done in two " -"different ways:" +"with storage variables inside a smart contract, we need to explicitly state " +"that we are accessing the `ContractState` by adding it as the first " +"parameter of the function. This can be done in two different ways:" msgstr "" -"无论函数是内部函数还是外部函数,它都可以修改或不修改合约的状态。当我们在智能合" -"约中声明与存储变量交互的函数时,\n" +"无论函数是内部函数还是外部函数,它都可以修改或不修改合约的状态。当我们在智能" +"合约中声明与存储变量交互的函数时,\n" "我们需要将 `ContractState`添加为函数的第一个参数,明确说明我们正在访问 合约的" "状态。这有两种不同的方法:" #: src/ch00/basics/visibility-mutability.md:17 +#, fuzzy +msgid "" +"If we want our function to be able to mutate the state of the contract, we " +"pass it by reference like this: `ref self: ContractState`." +msgstr "" +"- 如果我们希望我们的函数能够更改合约的状态,我们可以像这样通过引用来传递它:" +"ref self:ContractState`。\n" +"- 如果我们希望我们的函数是只读的,并且不更改合约的状态,我们可以通过快照传递" +"它,如下所示:`self:@ContractState`." + +#: src/ch00/basics/visibility-mutability.md:18 +#, fuzzy msgid "" -"- If we want our function to be able to mutate the state of the contract, we " -"pass it by reference like this: `ref self: ContractState`.\n" -"- If we want our function to be read-only and not mutate the state of the " +"If we want our function to be read-only and not mutate the state of the " "contract, we pass it by snapshot like this: `self: @ContractState`." msgstr "" "- 如果我们希望我们的函数能够更改合约的状态,我们可以像这样通过引用来传递它:" @@ -885,12 +667,13 @@ msgstr "" "它,如下所示:`self:@ContractState`." #: src/ch00/basics/visibility-mutability.md:20 +#, fuzzy msgid "" "Read-only functions, also called view functions, can be directly called " "without making a transaction. You can interact with them directly through a " -"RPC node to read the contract's state, and they're free to call!\n" -"External functions, that modify the contract's state, on the other side can " -"only be called by making a transaction." +"RPC node to read the contract's state, and they're free to call! External " +"functions, that modify the contract's state, on the other side can only be " +"called by making a transaction." msgstr "" "只读函数(也称为视图函数)可以直接调用,无需进行事务处理。你可以直接通过 RPC " "节点与它们交互,读取合约的状态,而且可以自由调用!\n" @@ -898,131 +681,59 @@ msgstr "" #: src/ch00/basics/visibility-mutability.md:23 msgid "" -"Internal functions can't be called externally, but the same principle applies " -"regarding state mutability." +"Internal functions can't be called externally, but the same principle " +"applies regarding state mutability." msgstr "内部函数不能被外部调用,同样的原则也适用于状态可变性。" #: src/ch00/basics/visibility-mutability.md:25 msgid "Let's take a look at a simple example contract to see these in action:" msgstr "让我们通过一个简单的合约示例来了解这些功能:" -#: src/ch00/basics/visibility-mutability.md:27 +#: src/ch00/basics/visibility-mutability.md:42 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IExampleContract {\n" -" fn set(ref self: TContractState, value: u32);\n" -" fn get(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ExampleContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -"\n" -" // The `abi(embed_v0)` attribute indicates that all the functions in this " +"// The `abi(embed_v0)` attribute indicates that all the functions in this " "implementation can be called externally.\n" " // Omitting this attribute would make all the functions in this " "implementation internal.\n" -" #[abi(embed_v0)]\n" -" impl ExampleContract of super::IExampleContract {\n" -" // The `set` function can be called externally because it is written " -"inside an implementation marked as `#[external]`.\n" -" // It can modify the contract's state as it is passed as a " -"reference.\n" -" fn set(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -"\n" -" // The `get` function can be called externally because it is written " -"inside an implementation marked as `#[external]`.\n" -" // However, it can't modify the contract's state is passed as a " -"snapshot: it is only a \"view\" function.\n" -" fn get(self: @ContractState) -> u32 {\n" -" // We can call an internal function from any functions within the " -"contract\n" -" PrivateFunctionsTrait::_read_value(self)\n" -" }\n" -" }\n" -"\n" -" // The lack of the `external` attribute indicates that all the functions " -"in this implementation can only be called internally.\n" -" // We name the trait `PrivateFunctionsTrait` to indicate that it is an " -"internal trait allowing us to call internal functions.\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" // The `_read_value` function is outside the implementation that is " -"marked as `#[abi(embed_v0)]`, so it's an _internal_ function\n" -" // and can only be called from within the contract.\n" -" // However, it can't modify the contract's state is passed as a " -"snapshot: it is only a \"view\" function.\n" -" fn _read_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IExampleContract {\n" -" fn set(ref self: TContractState, value: u32);\n" -" fn get(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ExampleContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -"\n" -" // The `abi(embed_v0)` attribute indicates that all the functions in this " -"implementation can be called externally.\n" -" // Omitting this attribute would make all the functions in this " -"implementation internal.\n" -" #[abi(embed_v0)]\n" -" impl ExampleContract of super::IExampleContract {\n" -" // The `set` function can be called externally because it is written " -"inside an implementation marked as `#[external]`.\n" + +#: src/ch00/basics/visibility-mutability.md:46 +msgid "" +"// The `set` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" " // It can modify the contract's state as it is passed as a " "reference.\n" -" fn set(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -"\n" -" // The `get` function can be called externally because it is written " -"inside an implementation marked as `#[external]`.\n" +msgstr "" + +#: src/ch00/basics/visibility-mutability.md:52 +msgid "" +"// The `get` function can be called externally because it is written inside " +"an implementation marked as `#[external]`.\n" " // However, it can't modify the contract's state is passed as a " "snapshot: it is only a \"view\" function.\n" -" fn get(self: @ContractState) -> u32 {\n" -" // We can call an internal function from any functions within the " -"contract\n" -" PrivateFunctionsTrait::_read_value(self)\n" -" }\n" -" }\n" -"\n" -" // The lack of the `external` attribute indicates that all the functions " -"in this implementation can only be called internally.\n" +msgstr "" + +#: src/ch00/basics/visibility-mutability.md:55 +msgid "" +"// We can call an internal function from any functions within the contract\n" +msgstr "" + +#: src/ch00/basics/visibility-mutability.md:60 +msgid "" +"// The lack of the `external` attribute indicates that all the functions in " +"this implementation can only be called internally.\n" " // We name the trait `PrivateFunctionsTrait` to indicate that it is an " "internal trait allowing us to call internal functions.\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" // The `_read_value` function is outside the implementation that is " -"marked as `#[abi(embed_v0)]`, so it's an _internal_ function\n" +msgstr "" + +#: src/ch00/basics/visibility-mutability.md:64 +msgid "" +"// The `_read_value` function is outside the implementation that is marked " +"as `#[abi(embed_v0)]`, so it's an _internal_ function\n" " // and can only be called from within the contract.\n" " // However, it can't modify the contract's state is passed as a " "snapshot: it is only a \"view\" function.\n" -" fn _read_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" }\n" -"}\n" -"```" +msgstr "" #: src/ch00/basics/visibility-mutability.md:73 msgid "" @@ -1039,13 +750,9 @@ msgstr "" "blob/main/listings/ch00-getting-started/visibility/src/visibility.cairo) 中尝" "试它。" -#: src/ch00/basics/visibility-mutability.md:75 -#: src/ch00/interacting/interacting.md:4 -msgid "
Last change: 2023-10-19
" -msgstr "
Last change: 2023-10-19
" - #: src/ch00/basics/counter.md:1 -msgid "# Simple Counter" +#, fuzzy +msgid "Simple Counter" msgstr "# 简单计数器" #: src/ch00/basics/counter.md:3 @@ -1058,104 +765,35 @@ msgstr "这个合约是这样工作的:" #: src/ch00/basics/counter.md:7 msgid "" -"- The contract has a state variable called 'counter' that is initialized to " -"0.\n" -"\n" -"- When a user calls 'increment', the contract increments the counter by 1.\n" -"\n" -"- When a user calls 'decrement', the contract decrements the counter by 1." +"The contract has a state variable called 'counter' that is initialized to 0." msgstr "" -"- 合约有一个名为 'counter'的状态变量,初始化为 0。\n" -"\n" -"- 当用户调用 'increment'时,合约会将计数器递增 1。\n" -"\n" -"- 当用户调用 'decrement'时,合约会将计数器递减 1。" -#: src/ch00/basics/counter.md:13 +#: src/ch00/basics/counter.md:9 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISimpleCounter {\n" -" fn get_current_count(self: @TContractState) -> u128;\n" -" fn increment(ref self: TContractState);\n" -" fn decrement(ref self: TContractState);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleCounter {\n" -" #[storage]\n" -" struct Storage {\n" -" // Counter variable\n" -" counter: u128,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, init_value: u128) {\n" -" // Store initial value\n" -" self.counter.write(init_value);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleCounter of super::ISimpleCounter {\n" -" fn get_current_count(self: @ContractState) -> u128 {\n" -" return self.counter.read();\n" -" }\n" -"\n" -" fn increment(ref self: ContractState) {\n" -" // Store counter value + 1\n" -" let counter = self.counter.read() + 1;\n" -" self.counter.write(counter);\n" -" }\n" -" fn decrement(ref self: ContractState) {\n" -" // Store counter value - 1\n" -" let counter = self.counter.read() - 1;\n" -" self.counter.write(counter);\n" -" }\n" -" }\n" -"}\n" -"```" +"When a user calls 'increment', the contract increments the counter by 1." +msgstr "" + +#: src/ch00/basics/counter.md:11 +msgid "" +"When a user calls 'decrement', the contract decrements the counter by 1." +msgstr "" + +#: src/ch00/basics/counter.md:25 +#, fuzzy +msgid "// Counter variable\n" +msgstr "计数器示例" + +#: src/ch00/basics/counter.md:31 +msgid "// Store initial value\n" +msgstr "" + +#: src/ch00/basics/counter.md:42 +msgid "// Store counter value + 1\n" +msgstr "" + +#: src/ch00/basics/counter.md:47 +msgid "// Store counter value - 1\n" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISimpleCounter {\n" -" fn get_current_count(self: @TContractState) -> u128;\n" -" fn increment(ref self: TContractState);\n" -" fn decrement(ref self: TContractState);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleCounter {\n" -" #[storage]\n" -" struct Storage {\n" -" // Counter variable\n" -" counter: u128,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, init_value: u128) {\n" -" // Store initial value\n" -" self.counter.write(init_value);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleCounter of super::ISimpleCounter {\n" -" fn get_current_count(self: @ContractState) -> u128 {\n" -" return self.counter.read();\n" -" }\n" -"\n" -" fn increment(ref self: ContractState) {\n" -" // Store counter value + 1\n" -" let counter = self.counter.read() + 1;\n" -" self.counter.write(counter);\n" -" }\n" -" fn decrement(ref self: ContractState) {\n" -" // Store counter value - 1\n" -" let counter = self.counter.read() - 1;\n" -" self.counter.write(counter);\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/counter.md:54 msgid "" @@ -1172,14 +810,6 @@ msgstr "" "blob/main/listings/ch00-getting-started/counter/src/contracts.cairo) 中尝试" "它。" -#: src/ch00/basics/counter.md:56 -msgid "
Last change: 2023-11-04
" -msgstr "
Last change: 2023-11-04
" - -#: src/ch00/basics/mappings.md:1 -msgid "# Mappings" -msgstr "# 映射" - #: src/ch00/basics/mappings.md:3 msgid "" "Maps are a key-value data structure used to store data within a smart " @@ -1192,13 +822,14 @@ msgstr "" "中使用,不能用在其他地方。" #: src/ch00/basics/mappings.md:5 +#, fuzzy msgid "" "Here we demonstrate how to use the `LegacyMap` type within a Cairo contract, " "to map between a key of type `ContractAddress` and value of type `felt252`. " -"The key-value types are specified within angular brackets <>. We write to the " -"map by calling the `write()` method, passing in both the key and value. " -"Similarly, we can read the value associated with a given key by calling the " -"`read()` method and passing in the relevant key." +"The key-value types are specified within angular brackets \\<\\>. We write " +"to the map by calling the `write()` method, passing in both the key and " +"value. Similarly, we can read the value associated with a given key by " +"calling the `read()` method and passing in the relevant key." msgstr "" "在此,我们演示如何在Cairo合约中使用 `LegacyMap` 类型,在 `ContractAddress` 类" "型的键和 `felt252` 类型的值之间进行映射。键值类型在角括号 <> 中指定。我们通过" @@ -1211,95 +842,34 @@ msgstr "一些补充说明:" #: src/ch00/basics/mappings.md:9 msgid "" -"- More complex key-value mappings are possible, for example we could use " +"More complex key-value mappings are possible, for example we could use " "`LegacyMap::<(ContractAddress, ContractAddress), felt252>` to create an " -"allowance on an ERC20 token contract.\n" -"\n" -"- In mappings, the address of the value at key `k_1,...,k_n` is `h(..." +"allowance on an ERC20 token contract." +msgstr "" + +#: src/ch00/basics/mappings.md:11 +#, fuzzy +msgid "" +"In mappings, the address of the value at key `k_1,...,k_n` is `h(..." "h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)` where `ℎ` is the Pedersen " -"hash and the final value is taken `mod2251−256`. You can learn more about the " -"contract storage layout in the [Starknet Documentation](https://docs.starknet." -"io/documentation/architecture_and_concepts/Contracts/contract-storage/" -"#storage_variables)" +"hash and the final value is taken `mod2251−256`. You can learn more about " +"the contract storage layout in the [Starknet Documentation](https://docs." +"starknet.io/documentation/architecture_and_concepts/Contracts/contract-" +"storage/#storage_variables)" msgstr "" "- 也有更复杂的键值对映射,例如,我们可以使用 `LegacyMap::<(ContractAddress, " "ContractAddress), felt252>` 在 ERC20 代币合约上创建一个代币授权许可。\n" "\n" "- 在映射中,键`k_1,...,k_n`处的值的地址是`h(...h(h(sn_keccak(variable_name)," "k_1),k_2),...,k_n)`,其中 `ℎ` 是 Pedersen 哈希值,最终值取`mod2251-256`。有关" -"合约存储布局的更多信息,请参阅 [Starknet Documentation](https://docs.starknet." -"io/documentation/architecture_and_concepts/Contracts/contract-storage/" -"#storage_variables)。" +"合约存储布局的更多信息,请参阅 [Starknet Documentation](https://docs." +"starknet.io/documentation/architecture_and_concepts/Contracts/contract-" +"storage/#storage_variables)。" -#: src/ch00/basics/mappings.md:13 +#: src/ch00/basics/mappings.md:28 msgid "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IMapContract {\n" -" fn set(ref self: TContractState, key: ContractAddress, value: felt252);\n" -" fn get(self: @TContractState, key: ContractAddress) -> felt252;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod MapContract {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" // The `LegacyMap` type is only available inside the `Storage` " -"struct.\n" -" map: LegacyMap::,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl MapContractImpl of super::IMapContract {\n" -" fn set(ref self: ContractState, key: ContractAddress, value: felt252) " -"{\n" -" self.map.write(key, value);\n" -" }\n" -"\n" -" fn get(self: @ContractState, key: ContractAddress) -> felt252 {\n" -" self.map.read(key)\n" -" }\n" -" }\n" -"}\n" -"```" +"// The `LegacyMap` type is only available inside the `Storage` struct.\n" msgstr "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IMapContract {\n" -" fn set(ref self: TContractState, key: ContractAddress, value: felt252);\n" -" fn get(self: @TContractState, key: ContractAddress) -> felt252;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod MapContract {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" // The `LegacyMap` type is only available inside the `Storage` " -"struct.\n" -" map: LegacyMap::,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl MapContractImpl of super::IMapContract {\n" -" fn set(ref self: ContractState, key: ContractAddress, value: felt252) " -"{\n" -" self.map.write(key, value);\n" -" }\n" -"\n" -" fn get(self: @ContractState, key: ContractAddress) -> felt252 {\n" -" self.map.read(key)\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/mappings.md:44 msgid "" @@ -1316,20 +886,17 @@ msgstr "" "blob/main/listings/ch00-getting-started/mappings/src/mappings.cairo) 中尝试" "它。" -#: src/ch00/basics/errors.md:1 -msgid "# Errors" -msgstr "# 错误" - #: src/ch00/basics/errors.md:3 +#, fuzzy msgid "" "Errors can be used to handle validation and other conditions that may occur " -"during the execution of a smart contract.\n" -"If an error is thrown during the execution of a smart contract call, the " -"execution is stopped and any changes made during the transaction are reverted." +"during the execution of a smart contract. If an error is thrown during the " +"execution of a smart contract call, the execution is stopped and any changes " +"made during the transaction are reverted." msgstr "" "错误可用于处理智能合约执行过程中可能发生的验证和其他条件。\n" -"如果在执行智能合约调用期间抛出错误,则将停止执行,并恢复在交易期间所做的任何更" -"改。" +"如果在执行智能合约调用期间抛出错误,则将停止执行,并恢复在交易期间所做的任何" +"更改。" #: src/ch00/basics/errors.md:6 msgid "To throw an error, use the `assert` or `panic` functions:" @@ -1337,16 +904,18 @@ msgstr "要抛出错误,请使用 `assert` 或 `panic`函数:" #: src/ch00/basics/errors.md:8 msgid "" -"- `assert` is used to validate conditions.\n" -" If the check fails, an error is thrown along with a specified value, often " -"a message.\n" -" It's similar to the `require` statement in Solidity.\n" -"\n" -"- `panic` immediately halt the execution with the given error value.\n" -" It should be used when the condition to check is complex and for internal " -"errors. It's similar to the `revert` statement in Solidity.\n" -" (Use `panic_with_felt252` to be able to directly pass a felt252 as the " -"error value)" +"`assert` is used to validate conditions. If the check fails, an error is " +"thrown along with a specified value, often a message. It's similar to the " +"`require` statement in Solidity." +msgstr "" + +#: src/ch00/basics/errors.md:12 +#, fuzzy +msgid "" +"`panic` immediately halt the execution with the given error value. It should " +"be used when the condition to check is complex and for internal errors. It's " +"similar to the `revert` statement in Solidity. (Use `panic_with_felt252` to " +"be able to directly pass a felt252 as the error value)" msgstr "" "- 'assert' 用于验证条件。\n" " 如果检查失败,则会引发错误以及指定的值,通常是一条消息。\n" @@ -1361,65 +930,15 @@ msgstr "" msgid "Here's a simple example that demonstrates the use of these functions:" msgstr "下面是一个简单的示例,演示了这些函数的用法:" -#: src/ch00/basics/errors.md:18 +#: src/ch00/basics/errors.md:32 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IErrorsExample {\n" -" fn test_assert(self: @TContractState, i: u256);\n" -" fn test_panic(self: @TContractState, i: u256);\n" -"}\n" -"#[starknet::contract]\n" -"mod ErrorsExample {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ErrorsExample of super::IErrorsExample {\n" -" fn test_assert(self: @ContractState, i: u256) {\n" -" // Assert used to validate a condition\n" +"// Assert used to validate a condition\n" " // and abort execution if the condition is not met\n" -" assert(i > 0, 'i must be greater than 0');\n" -" }\n" -"\n" -" fn test_panic(self: @ContractState, i: u256) {\n" -" if (i == 0) {\n" -" // Panic used to abort execution directly\n" -" panic_with_felt252('i must not be 0');\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IErrorsExample {\n" -" fn test_assert(self: @TContractState, i: u256);\n" -" fn test_panic(self: @TContractState, i: u256);\n" -"}\n" -"#[starknet::contract]\n" -"mod ErrorsExample {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ErrorsExample of super::IErrorsExample {\n" -" fn test_assert(self: @ContractState, i: u256) {\n" -" // Assert used to validate a condition\n" -" // and abort execution if the condition is not met\n" -" assert(i > 0, 'i must be greater than 0');\n" -" }\n" -"\n" -" fn test_panic(self: @ContractState, i: u256) {\n" -" if (i == 0) {\n" -" // Panic used to abort execution directly\n" -" panic_with_felt252('i must not be 0');\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" + +#: src/ch00/basics/errors.md:39 +msgid "// Panic used to abort execution directly\n" +msgstr "" #: src/ch00/basics/errors.md:46 msgid "" @@ -1433,89 +952,20 @@ msgstr "" "contract/0x0022664463FF0b711CC9B549a9E87d65A0882bB1D29338C4108696B8F2216a40) " "上访问合约或在 [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/errors/src/simple_errors.cairo) 中尝试" -"它。" +"blob/main/listings/ch00-getting-started/errors/src/simple_errors.cairo) 中尝" +"试它。" #: src/ch00/basics/errors.md:48 -msgid "## Custom errors" +#, fuzzy +msgid "Custom errors" msgstr "## 自定义错误" #: src/ch00/basics/errors.md:50 msgid "" -"You can make error handling easier by defining your error codes in a specific " -"module." +"You can make error handling easier by defining your error codes in a " +"specific module." msgstr "您可以通过在特定模块中定义错误代码来简化错误处理。" -#: src/ch00/basics/errors.md:52 -msgid "" -"```rust\n" -"mod Errors {\n" -" const NOT_POSITIVE: felt252 = 'must be greater than 0';\n" -" const NOT_NULL: felt252 = 'must not be null';\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ICustomErrorsExample {\n" -" fn test_assert(self: @TContractState, i: u256);\n" -" fn test_panic(self: @TContractState, i: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod CustomErrorsExample {\n" -" use super::Errors;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl CustomErrorsExample of super::ICustomErrorsExample {\n" -" fn test_assert(self: @ContractState, i: u256) {\n" -" assert(i > 0, Errors::NOT_POSITIVE);\n" -" }\n" -"\n" -" fn test_panic(self: @ContractState, i: u256) {\n" -" if (i == 0) {\n" -" panic_with_felt252(Errors::NOT_NULL);\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"mod Errors {\n" -" const NOT_POSITIVE: felt252 = 'must be greater than 0';\n" -" const NOT_NULL: felt252 = 'must not be null';\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ICustomErrorsExample {\n" -" fn test_assert(self: @TContractState, i: u256);\n" -" fn test_panic(self: @TContractState, i: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod CustomErrorsExample {\n" -" use super::Errors;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl CustomErrorsExample of super::ICustomErrorsExample {\n" -" fn test_assert(self: @ContractState, i: u256) {\n" -" assert(i > 0, Errors::NOT_POSITIVE);\n" -" }\n" -"\n" -" fn test_panic(self: @ContractState, i: u256) {\n" -" if (i == 0) {\n" -" panic_with_felt252(Errors::NOT_NULL);\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch00/basics/errors.md:85 msgid "" "Visit contract on [Voyager](https://goerli.voyager.online/" @@ -1528,11 +978,12 @@ msgstr "" "contract/0x0501CD5da5B453a18515B5A20b8029bd7583DFE7a399ad9f79c284F7829e4A57) " "上访问 contract 或在 [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/errors/src/custom_errors.cairo) 中尝试" -"它。" +"blob/main/listings/ch00-getting-started/errors/src/custom_errors.cairo) 中尝" +"试它。" #: src/ch00/basics/errors.md:87 -msgid "## Vault example" +#, fuzzy +msgid "Vault example" msgstr "## Vault 示例" #: src/ch00/basics/errors.md:89 @@ -1541,101 +992,13 @@ msgid "" "contract:" msgstr "下面是另一个示例,演示了在更复杂的合约中使用错误:" -#: src/ch00/basics/errors.md:91 -msgid "" -"```rust\n" -"mod VaultErrors {\n" -" const INSUFFICIENT_BALANCE: felt252 = 'insufficient_balance';\n" -"// you can define more errors here\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait IVaultErrorsExample {\n" -" fn deposit(ref self: TContractState, amount: u256);\n" -" fn withdraw(ref self: TContractState, amount: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod VaultErrorsExample {\n" -" use super::VaultErrors;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" balance: u256,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl VaultErrorsExample of super::IVaultErrorsExample {\n" -" fn deposit(ref self: ContractState, amount: u256) {\n" -" let mut balance = self.balance.read();\n" -" balance = balance + amount;\n" -" self.balance.write(balance);\n" -" }\n" -"\n" -" fn withdraw(ref self: ContractState, amount: u256) {\n" -" let mut balance = self.balance.read();\n" -"\n" -" assert(balance >= amount, VaultErrors::INSUFFICIENT_BALANCE);\n" -"\n" -" // Or using panic:\n" -" if (balance >= amount) {\n" -" panic_with_felt252(VaultErrors::INSUFFICIENT_BALANCE);\n" -" }\n" -"\n" -" let balance = balance - amount;\n" -"\n" -" self.balance.write(balance);\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/ch00/basics/errors.md:93 +msgid "// you can define more errors here\n" +msgstr "" + +#: src/ch00/basics/errors.md:125 +msgid "// Or using panic:\n" msgstr "" -"```rust\n" -"mod VaultErrors {\n" -" const INSUFFICIENT_BALANCE: felt252 = 'insufficient_balance';\n" -"// you can define more errors here\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait IVaultErrorsExample {\n" -" fn deposit(ref self: TContractState, amount: u256);\n" -" fn withdraw(ref self: TContractState, amount: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod VaultErrorsExample {\n" -" use super::VaultErrors;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" balance: u256,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl VaultErrorsExample of super::IVaultErrorsExample {\n" -" fn deposit(ref self: ContractState, amount: u256) {\n" -" let mut balance = self.balance.read();\n" -" balance = balance + amount;\n" -" self.balance.write(balance);\n" -" }\n" -"\n" -" fn withdraw(ref self: ContractState, amount: u256) {\n" -" let mut balance = self.balance.read();\n" -"\n" -" assert(balance >= amount, VaultErrors::INSUFFICIENT_BALANCE);\n" -"\n" -" // Or using panic:\n" -" if (balance >= amount) {\n" -" panic_with_felt252(VaultErrors::INSUFFICIENT_BALANCE);\n" -" }\n" -"\n" -" let balance = balance - amount;\n" -"\n" -" self.balance.write(balance);\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/errors.md:137 msgid "" @@ -1652,25 +1015,22 @@ msgstr "" "blob/main/listings/ch00-getting-started/errors/src/vault_errors.cairo) 中尝试" "它。" -#: src/ch00/basics/events.md:1 -msgid "# Events" -msgstr "# 事件" - #: src/ch00/basics/events.md:3 +#, fuzzy msgid "" "Events are a way to emit data from a contract. All events must be defined in " -"the `Event` enum, which must be annotated with the `#[event]` attribute.\n" -"An event is defined as struct that derives the `#[starknet::Event]` trait. " -"The fields of that struct correspond to the data that will be emitted. An " -"event can be indexed for easy and fast access when querying the data at a " -"later time. Events data can be indexed by adding a `#[key]` attribute to a " -"field member." +"the `Event` enum, which must be annotated with the `#[event]` attribute. An " +"event is defined as struct that derives the `#[starknet::Event]` trait. The " +"fields of that struct correspond to the data that will be emitted. An event " +"can be indexed for easy and fast access when querying the data at a later " +"time. Events data can be indexed by adding a `#[key]` attribute to a field " +"member." msgstr "" "事件是从合约发出数据的一种方式。所有事件都必须在`Event`枚举中定义,该枚举必须" "使用`#[event]`属性进行注释。\n" -"事件被定义为派生`#[starknet::Event]`特征的结构。该结构的字段对应于将要发出的数" -"据。可以对事件编制索引,以便在以后查询数据时轻松快速地访问。可以通过向字段成员" -"添加`#[key]` 属性来索引事件数据。" +"事件被定义为派生`#[starknet::Event]`特征的结构。该结构的字段对应于将要发出的" +"数据。可以对事件编制索引,以便在以后查询数据时轻松快速地访问。可以通过向字段" +"成员添加`#[key]` 属性来索引事件数据。" #: src/ch00/basics/events.md:6 msgid "" @@ -1680,131 +1040,31 @@ msgstr "" "下面是合约使用事件的简单示例,这些事件在每次计数器通过“increment”函数递增时发" "出一个事件:" -#: src/ch00/basics/events.md:8 +#: src/ch00/basics/events.md:18 +#, fuzzy +msgid "// Counter value\n" +msgstr "计数器示例" + +#: src/ch00/basics/events.md:24 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IEventCounter {\n" -" fn increment(ref self: TContractState);\n" -"}\n" -"#[starknet::contract]\n" -"mod EventCounter {\n" -" use starknet::{get_caller_address, ContractAddress};\n" -" #[storage]\n" -" struct Storage {\n" -" // Counter value\n" -" counter: u128,\n" -" }\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" // The event enum must be annotated with the `#[event]` attribute.\n" +"// The event enum must be annotated with the `#[event]` attribute.\n" " // It must also derive the `Drop` and `starknet::Event` traits.\n" -" enum Event {\n" -" CounterIncreased: CounterIncreased,\n" -" UserIncreaseCounter: UserIncreaseCounter\n" -" }\n" -"\n" -" // By deriving the `starknet::Event` trait, we indicate to the compiler " -"that\n" -" // this struct will be used when emitting events.\n" -" #[derive(Drop, starknet::Event)]\n" -" struct CounterIncreased {\n" -" amount: u128\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct UserIncreaseCounter {\n" -" // The `#[key]` attribute indicates that this event will be indexed.\n" -" #[key]\n" -" user: ContractAddress,\n" -" new_value: u128,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl EventCounter of super::IEventCounter {\n" -" fn increment(ref self: ContractState) {\n" -" let mut counter = self.counter.read();\n" -" counter += 1;\n" -" self.counter.write(counter);\n" -" // Emit event\n" -" self.emit(Event::CounterIncreased(CounterIncreased { amount: " -"1 }));\n" -" self\n" -" .emit(\n" -" Event::UserIncreaseCounter(\n" -" UserIncreaseCounter {\n" -" user: get_caller_address(), new_value: self." -"counter.read()\n" -" }\n" -" )\n" -" );\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IEventCounter {\n" -" fn increment(ref self: TContractState);\n" -"}\n" -"#[starknet::contract]\n" -"mod EventCounter {\n" -" use starknet::{get_caller_address, ContractAddress};\n" -" #[storage]\n" -" struct Storage {\n" -" // Counter value\n" -" counter: u128,\n" -" }\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" // The event enum must be annotated with the `#[event]` attribute.\n" -" // It must also derive the `Drop` and `starknet::Event` traits.\n" -" enum Event {\n" -" CounterIncreased: CounterIncreased,\n" -" UserIncreaseCounter: UserIncreaseCounter\n" -" }\n" -"\n" -" // By deriving the `starknet::Event` trait, we indicate to the compiler " + +#: src/ch00/basics/events.md:31 +msgid "" +"// By deriving the `starknet::Event` trait, we indicate to the compiler " "that\n" " // this struct will be used when emitting events.\n" -" #[derive(Drop, starknet::Event)]\n" -" struct CounterIncreased {\n" -" amount: u128\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct UserIncreaseCounter {\n" -" // The `#[key]` attribute indicates that this event will be indexed.\n" -" #[key]\n" -" user: ContractAddress,\n" -" new_value: u128,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl EventCounter of super::IEventCounter {\n" -" fn increment(ref self: ContractState) {\n" -" let mut counter = self.counter.read();\n" -" counter += 1;\n" -" self.counter.write(counter);\n" -" // Emit event\n" -" self.emit(Event::CounterIncreased(CounterIncreased { amount: " -"1 }));\n" -" self\n" -" .emit(\n" -" Event::UserIncreaseCounter(\n" -" UserIncreaseCounter {\n" -" user: get_caller_address(), new_value: self." -"counter.read()\n" -" }\n" -" )\n" -" );\n" -" }\n" -" }\n" -"}\n" -"```" +msgstr "" + +#: src/ch00/basics/events.md:40 +msgid "// The `#[key]` attribute indicates that this event will be indexed.\n" +msgstr "" + +#: src/ch00/basics/events.md:52 +msgid "// Emit event\n" +msgstr "" #: src/ch00/basics/events.md:66 msgid "" @@ -1820,89 +1080,25 @@ msgstr "" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" "blob/main/listings/ch00-getting-started/events/src/counter.cairo) 中尝试它。" -#: src/ch00/basics/storing-custom-types.md:1 -msgid "# Storing Custom Types" -msgstr "# 存储自定义类型" - #: src/ch00/basics/storing-custom-types.md:3 msgid "" "While native types can be stored in a contract's storage without any " "additional work, custom types require a bit more work. This is because at " "compile time, the compiler does not know how to store custom types in " -"storage. To solve this, we need to implement the `Store` trait for our custom " -"type. Hopefully, we can just derive this trait for our custom type - unless " -"it contains arrays or dictionaries." +"storage. To solve this, we need to implement the `Store` trait for our " +"custom type. Hopefully, we can just derive this trait for our custom type - " +"unless it contains arrays or dictionaries." msgstr "" -"虽然本机类型可以存储在合约的存储中,而无需任何额外的工作,但自定义类型需要更多" -"的工作。这是因为在编译时,编译器不知道如何在存储中存储自定义类型。为了解决这个" -"问题,我们需要为我们的自定义类型实现 `Store`特征。希望我们可以为我们的自定义类" -"型派生这个特征 - 除非它包含数组或字典。" +"虽然本机类型可以存储在合约的存储中,而无需任何额外的工作,但自定义类型需要更" +"多的工作。这是因为在编译时,编译器不知道如何在存储中存储自定义类型。为了解决" +"这个问题,我们需要为我们的自定义类型实现 `Store`特征。希望我们可以为我们的自" +"定义类型派生这个特征 - 除非它包含数组或字典。" -#: src/ch00/basics/storing-custom-types.md:5 +#: src/ch00/basics/storing-custom-types.md:10 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStoringCustomType {\n" -" fn set_person(ref self: TContractState, person: Person);\n" -"}\n" -"\n" "// Deriving the starknet::Store trait\n" "// allows us to store the `Person` struct in the contract's storage.\n" -"#[derive(Drop, Serde, Copy, starknet::Store)]\n" -"struct Person {\n" -" age: u8,\n" -" name: felt252\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod StoringCustomType {\n" -" use super::Person;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" person: Person\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StoringCustomType of super::IStoringCustomType {\n" -" fn set_person(ref self: ContractState, person: Person) {\n" -" self.person.write(person);\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStoringCustomType {\n" -" fn set_person(ref self: TContractState, person: Person);\n" -"}\n" -"\n" -"// Deriving the starknet::Store trait\n" -"// allows us to store the `Person` struct in the contract's storage.\n" -"#[derive(Drop, Serde, Copy, starknet::Store)]\n" -"struct Person {\n" -" age: u8,\n" -" name: felt252\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod StoringCustomType {\n" -" use super::Person;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" person: Person\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StoringCustomType of super::IStoringCustomType {\n" -" fn set_person(ref self: ContractState, person: Person) {\n" -" self.person.write(person);\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/storing-custom-types.md:37 msgid "" @@ -1915,105 +1111,39 @@ msgstr "" "com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/" "storing_custom_types/src/contract.cairo) 中尝试这个合约。" -#: src/ch00/basics/custom-types-in-entrypoints.md:1 -msgid "# Custom types in entrypoints" -msgstr "# 入口点中的自定义类型" - #: src/ch00/basics/custom-types-in-entrypoints.md:3 +#, fuzzy msgid "" "Using custom types in entrypoints requires our type to implement the `Serde` " "trait. This is because when calling an entrypoint, the input is sent as an " "array of `felt252` to the entrypoint, and we need to be able to deserialize " "it into our custom type. Similarly, when returning a custom type from an " -"entrypoint, we need to be able to serialize it into an array of `felt252`.\n" +"entrypoint, we need to be able to serialize it into an array of `felt252`. " "Thankfully, we can just derive the `Serde` trait for our custom type." msgstr "" -"在入口点中使用自定义类型需要我们的类型来实现`Serde`trait。这是因为在调用入口点" -"时,输入以`felt252` 数组的形式发送到入口点,我们需要能够将其反序列化为我们的自" -"定义类型。同样,当从入口点返回自定义类型时,我们需要能够将其序列化为`felt252` " -"数组。\n" +"在入口点中使用自定义类型需要我们的类型来实现`Serde`trait。这是因为在调用入口" +"点时,输入以`felt252` 数组的形式发送到入口点,我们需要能够将其反序列化为我们" +"的自定义类型。同样,当从入口点返回自定义类型时,我们需要能够将其序列化为" +"`felt252` 数组。\n" "值得庆幸的是,我们可以为我们的自定义类型派生`Serde` 特征。" -#: src/ch00/basics/custom-types-in-entrypoints.md:6 +#: src/ch00/basics/custom-types-in-entrypoints.md:18 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISerdeCustomType {\n" -" fn person_input(ref self: TContractState, person: SerdeCustomType::" -"Person);\n" -" fn person_output(self: @TContractState) -> SerdeCustomType::Person;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SerdeCustomType {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" // Deriving the `Serde` trait allows us to use\n" +"// Deriving the `Serde` trait allows us to use\n" " // the Person type as an entrypoint parameter and return value\n" -" #[derive(Drop, Serde)]\n" -" struct Person {\n" -" age: u8,\n" -" name: felt252\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SerdeCustomType of super::ISerdeCustomType {\n" -" fn person_input(ref self: ContractState, person: Person) {}\n" -"\n" -" fn person_output(self: @ContractState) -> Person {\n" -" Person { age: 10, name: 'Joe' }\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISerdeCustomType {\n" -" fn person_input(ref self: TContractState, person: SerdeCustomType::" -"Person);\n" -" fn person_output(self: @TContractState) -> SerdeCustomType::Person;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SerdeCustomType {\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" // Deriving the `Serde` trait allows us to use\n" -" // the Person type as an entrypoint parameter and return value\n" -" #[derive(Drop, Serde)]\n" -" struct Person {\n" -" age: u8,\n" -" name: felt252\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SerdeCustomType of super::ISerdeCustomType {\n" -" fn person_input(ref self: ContractState, person: Person) {}\n" -"\n" -" fn person_output(self: @ContractState) -> Person {\n" -" Person { age: 10, name: 'Joe' }\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch00/basics/custom-types-in-entrypoints.md:37 msgid "" "Play with this contract in [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/custom_type_serde/src/contract.cairo)." +"blob/main/listings/ch00-getting-started/custom_type_serde/src/contract." +"cairo)." msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." "com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/" "custom_type_serde/src/contract.cairo) 中尝试这个合约。" -#: src/ch00/basics/documentation.md:1 -msgid "# Documentation" -msgstr "# 文档" - #: src/ch00/basics/documentation.md:3 msgid "" "It's important to take the time to document your code. It will helps " @@ -2026,7 +1156,8 @@ msgid "In Cairo, you can add comments with `//`." msgstr "在Cairo,您可以使用“//”添加注释。" #: src/ch00/basics/documentation.md:7 -msgid "### Best Practices:" +#, fuzzy +msgid "Best Practices:" msgstr "### 最佳实践:" #: src/ch00/basics/documentation.md:9 @@ -2038,28 +1169,27 @@ msgstr "" "rust-by-example/meta/doc.html)。" #: src/ch00/basics/documentation.md:11 -msgid "### Contract Interface:" +#, fuzzy +msgid "Contract Interface:" msgstr "### 合约接口:" #: src/ch00/basics/documentation.md:13 +#, fuzzy msgid "" "In smart contracts, you will often have a trait that defines the contract's " -"interface (with `#[starknet::interface]`).\n" -"This is the perfect place to include detailed documentation explaining the " -"purpose and functionality of the contract entry points. You can follow this " -"template:" +"interface (with `#[starknet::interface]`). This is the perfect place to " +"include detailed documentation explaining the purpose and functionality of " +"the contract entry points. You can follow this template:" msgstr "" "在智能合约中,你通常会有一个定义合约接口的trait(带有'#[starknet::" "interface]')。\n" -"这是包含详细文档的理想场所,这些文档解释了合约入口点的用途和功能。您可以遵循以" -"下模板:" +"这是包含详细文档的理想场所,这些文档解释了合约入口点的用途和功能。您可以遵循" +"以下模板:" -#: src/ch00/basics/documentation.md:16 +#: src/ch00/basics/documentation.md:19 +#, fuzzy msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IContract {\n" -" /// High-level description of the function\n" +"/// High-level description of the function\n" " ///\n" " /// # Arguments\n" " ///\n" @@ -2069,9 +1199,6 @@ msgid "" " /// # Returns\n" " ///\n" " /// High-level description of the return value\n" -" fn do_something(ref self: TContractState, arg_1: T_arg_1) -> T_return;\n" -"}\n" -"```" msgstr "" "```rust\n" "#[starknet::interface]\n" @@ -2093,14 +1220,15 @@ msgstr "" #: src/ch00/basics/documentation.md:33 msgid "" "Keep in mind that this should not describe the implementation details of the " -"function, but rather the high-level purpose and functionality of the contract " -"from the perspective of a user." +"function, but rather the high-level purpose and functionality of the " +"contract from the perspective of a user." msgstr "" "请记住,这不应该描述函数的实现细节,而应该从用户的角度描述合约的高级目的和功" "能。" #: src/ch00/basics/documentation.md:35 -msgid "### Implementation Details:" +#, fuzzy +msgid "Implementation Details:" msgstr "### 实装细节:" #: src/ch00/basics/documentation.md:37 @@ -2110,26 +1238,15 @@ msgid "" msgstr "在编写合约逻辑时,可以添加注释来描述函数的技术实现细节。" #: src/ch00/basics/documentation.md:39 +#, fuzzy msgid "" -"> Avoid over-commenting: Comments should provide additional value and clarity." +"Avoid over-commenting: Comments should provide additional value and clarity." msgstr "> 避免过度注释:注释应提供额外的价值和清晰度。" -#: src/ch00/basics/documentation.md:41 -msgid "
Last change: 2023-12-05
" -msgstr "
Last change: 2023-12-05
" - -#: src/ch00/interacting/interacting.md:1 -msgid "# Deploy and interact with contracts" -msgstr "# 部署合约并与合约交互" - #: src/ch00/interacting/interacting.md:3 msgid "In this chapter, we will see how to deploy and interact with contracts." msgstr "在本章中,我们将了解如何部署合约并与之交互。" -#: src/ch00/interacting/interfaces-traits.md:1 -msgid "# Contract interfaces and Traits generation" -msgstr "# 合约接口和Trait生成" - #: src/ch00/interacting/interfaces-traits.md:3 msgid "" "Contract interfaces define the structure and behavior of a contract, serving " @@ -2138,8 +1255,8 @@ msgid "" "the [Cairo Book](https://book.cairo-lang.org/ch99-01-02-a-simple-contract." "html)." msgstr "" -"合约接口定义合约的结构和行为,充当合约的公共 ABI。它们列出了合约公开的所有函数" -"签名。接口的详细说明可以参考 [Cairo之书](https://book.cairo-lang.org/" +"合约接口定义合约的结构和行为,充当合约的公共 ABI。它们列出了合约公开的所有函" +"数签名。接口的详细说明可以参考 [Cairo之书](https://book.cairo-lang.org/" "ch99-01-02-a-simple-contract.html)。" #: src/ch00/interacting/interfaces-traits.md:5 @@ -2174,19 +1291,23 @@ msgid "" "l1 handler." msgstr "" "您可以使用`#[generate_trait]`属性隐式生成特定实现块的特征。此属性会自动生成一" -"个特征,其功能与已实现块中的函数相同,将`self`参数替换为通用的`TContractState`" -"参数。但是,您需要使用`#[abi(per_item)]` 属性注释块,并且每个函数都具有适当的" -"属性,具体取决于它是外部函数、构造函数还是 l1 处理程序。" +"个特征,其功能与已实现块中的函数相同,将`self`参数替换为通用的" +"`TContractState`参数。但是,您需要使用`#[abi(per_item)]` 属性注释块,并且每个" +"函数都具有适当的属性,具体取决于它是外部函数、构造函数还是 l1 处理程序。" #: src/ch00/interacting/interfaces-traits.md:11 msgid "In summary, there's two ways to handle interfaces:" msgstr "总之,有两种方法可以处理接口:" #: src/ch00/interacting/interfaces-traits.md:13 +msgid "Explicitly, by defining a trait annoted with `#[starknet::interface]`" +msgstr "" + +#: src/ch00/interacting/interfaces-traits.md:14 +#, fuzzy msgid "" -"- Explicitly, by defining a trait annoted with `#[starknet::interface]`\n" -"- Implicitly, by using `#[generate_trait]` combined with the " -"#[abi(per_item)]` attributes, and annotating each function inside the " +"Implicitly, by using `#[generate_trait]` combined with the " +"#\\[abi(per_item)\\]\\` attributes, and annotating each function inside the " "implementation block with the appropriate attribute." msgstr "" "- 显示地,通过定义一个用`#[starknet::interface]`标记的特征\n" @@ -2194,257 +1315,62 @@ msgstr "" "当的属性注释实现块中的每个函数。" #: src/ch00/interacting/interfaces-traits.md:16 -msgid "## Explicit interface" +#, fuzzy +msgid "Explicit interface" msgstr "## 显式接口" -#: src/ch00/interacting/interfaces-traits.md:18 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IExplicitInterfaceContract {\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn set_value(ref self: TContractState, value: u32);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ExplicitInterfaceContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ExplicitInterfaceContract of super::" -"IExplicitInterfaceContract {\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IExplicitInterfaceContract {\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn set_value(ref self: TContractState, value: u32);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ExplicitInterfaceContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ExplicitInterfaceContract of super::" -"IExplicitInterfaceContract {\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch00/interacting/interfaces-traits.md:45 msgid "" "Play with this contract in [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit.cairo)." +"blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit." +"cairo)." msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." "com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/" "interfaces_traits/src/explicit.cairo) 中尝试这个合约。" #: src/ch00/interacting/interfaces-traits.md:47 -msgid "## Implicit interface" +#, fuzzy +msgid "Implicit interface" msgstr "## 隐式接口" -#: src/ch00/interacting/interfaces-traits.md:49 -msgid "" -"```rust\n" -"#[starknet::contract]\n" -"mod ImplicitInterfaceContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(per_item)]\n" -" #[generate_trait]\n" -" impl ImplicitInterfaceContract of IImplicitInterfaceContract {\n" -" #[external(v0)]\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" #[external(v0)]\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::contract]\n" -"mod ImplicitInterfaceContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[abi(per_item)]\n" -" #[generate_trait]\n" -" impl ImplicitInterfaceContract of IImplicitInterfaceContract {\n" -" #[external(v0)]\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" #[external(v0)]\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch00/interacting/interfaces-traits.md:73 msgid "" "Play with this contract in [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo)." +"blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit." +"cairo)." msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." "com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/" "interfaces_traits/src/implicit.cairo) 中尝试这个合约。" #: src/ch00/interacting/interfaces-traits.md:75 +#, fuzzy msgid "" -"> Note: You can import an implicitly generated contract interface with `use " +"Note: You can import an implicitly generated contract interface with `use " "contract::{GeneratedContractInterface}`. However, the `Dispatcher` will not " "be generated automatically." msgstr "" -"> 注意:您可以使用`use contract::{GeneratedContractInterface}`导入隐式生成的合" -"约接口。但是,`Dispatcher`不会自动生成。" +"> 注意:您可以使用`use contract::{GeneratedContractInterface}`导入隐式生成的" +"合约接口。但是,`Dispatcher`不会自动生成。" #: src/ch00/interacting/interfaces-traits.md:77 -msgid "## Internal functions" +#, fuzzy +msgid "Internal functions" msgstr "## 内部函数" #: src/ch00/interacting/interfaces-traits.md:79 +#, fuzzy msgid "" -"You can also use `#[generate_trait]` for your internal functions.\n" -"Since this trait is generated in the context of the contract, you can define " -"pure functions as well (functions without the `self` parameter)." +"You can also use `#[generate_trait]` for your internal functions. Since this " +"trait is generated in the context of the contract, you can define pure " +"functions as well (functions without the `self` parameter)." msgstr "" "您还可以将`#[generate_trait]`用于内部函数。\n" -"由于此特征是在合约的上下文中生成的,因此您也可以定义纯函数(没有“self”参数的函" -"数)。" - -#: src/ch00/interacting/interfaces-traits.md:82 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IImplicitInternalContract {\n" -" fn add(ref self: TContractState, nb: u32);\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn get_const(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ImplicitInternalContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl InternalFunctions of InternalFunctionsTrait {\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" fn get_const() -> u32 {\n" -" 42\n" -" }\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState) {\n" -" self.set_value(0);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ImplicitInternalContract of super::" -"IImplicitInternalContract {\n" -" fn add(ref self: ContractState, nb: u32) {\n" -" self.set_value(self.value.read() + nb);\n" -" }\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" fn get_const(self: @ContractState) -> u32 {\n" -" self.get_const()\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IImplicitInternalContract {\n" -" fn add(ref self: TContractState, nb: u32);\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn get_const(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ImplicitInternalContract {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl InternalFunctions of InternalFunctionsTrait {\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" self.value.write(value);\n" -" }\n" -" fn get_const() -> u32 {\n" -" 42\n" -" }\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState) {\n" -" self.set_value(0);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ImplicitInternalContract of super::" -"IImplicitInternalContract {\n" -" fn add(ref self: ContractState, nb: u32) {\n" -" self.set_value(self.value.read() + nb);\n" -" }\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -" fn get_const(self: @ContractState) -> u32 {\n" -" self.get_const()\n" -" }\n" -" }\n" -"}\n" -"```" +"由于此特征是在合约的上下文中生成的,因此您也可以定义纯函数(没有“self”参数的" +"函数)。" #: src/ch00/interacting/interfaces-traits.md:127 msgid "" @@ -2457,30 +1383,22 @@ msgstr "" "com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/" "interfaces_traits/src/implicit_internal.cairo) 中尝试这个合约。" -#: src/ch00/interacting/interfaces-traits.md:129 -msgid "
Last change: 2023-11-26
" -msgstr "
Last change: 2023-11-26
" - -#: src/ch00/interacting/calling_other_contracts.md:1 -msgid "# Calling other contracts" -msgstr "# 调用其他合约" - #: src/ch00/interacting/calling_other_contracts.md:3 msgid "There are two different ways to call other contracts in Cairo." msgstr "在Cairo,有两种不同的方式可以调用其他合约。" #: src/ch00/interacting/calling_other_contracts.md:5 +#, fuzzy msgid "" "The easiest way to call other contracts is by using the dispatcher of the " -"contract you want to call.\n" -"You can read more about Dispatchers in the [Cairo Book](https://book.cairo-" -"lang.org/ch99-02-02-contract-dispatcher-library-dispatcher-and-system-calls." -"html#contract-dispatcher)" +"contract you want to call. You can read more about Dispatchers in the [Cairo " +"Book](https://book.cairo-lang.org/ch99-02-02-contract-dispatcher-library-" +"dispatcher-and-system-calls.html#contract-dispatcher)" msgstr "" "调用其他合约的最简单方法是使用要调用的合约的调度程序。\n" "您可以在 [Cairo Book](https://book.cairo-lang.org/ch99-02-02-contract-" -"dispatcher-library-dispatcher-and-system-calls.html#contract-dispatcher) 中阅" -"读有关 Dispatchers 的更多信息" +"dispatcher-library-dispatcher-and-system-calls.html#contract-dispatcher) 中" +"阅读有关 Dispatchers 的更多信息" #: src/ch00/interacting/calling_other_contracts.md:8 msgid "" @@ -2497,58 +1415,10 @@ msgid "" "interface]` attribute, and then import the `IContractDispatcher` and " "`IContractDispatcherTrait` items in your contract." msgstr "" -"为了使用调度程序调用其他合约,您需要将被调用合约的接口定义为使用 `#[starknet::" -"interface]` 属性注释的trait,然后将 `IContractDispatcher` 和 " +"为了使用调度程序调用其他合约,您需要将被调用合约的接口定义为使用 " +"`#[starknet::interface]` 属性注释的trait,然后将 `IContractDispatcher` 和 " "`IContractDispatcherTrait` 项导入到合约中。" -#: src/ch00/interacting/calling_other_contracts.md:12 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ICallee {\n" -" fn set_value(ref self: TContractState, value: u128) -> u128;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod Callee {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u128,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ICalleeImpl of super::ICallee {\n" -" fn set_value(ref self: ContractState, value: u128) -> u128 {\n" -" self.value.write(value);\n" -" value\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ICallee {\n" -" fn set_value(ref self: TContractState, value: u128) -> u128;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod Callee {\n" -" #[storage]\n" -" struct Storage {\n" -" value: u128,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ICalleeImpl of super::ICallee {\n" -" fn set_value(ref self: ContractState, value: u128) -> u128 {\n" -" self.value.write(value);\n" -" value\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch00/interacting/calling_other_contracts.md:34 msgid "" "Visit contract on [Voyager](https://goerli.voyager.online/" @@ -2565,77 +1435,15 @@ msgstr "" "blob/main/listings/ch00-getting-started/calling_other_contracts/src/callee." "cairo)中尝试它。" -#: src/ch00/interacting/calling_other_contracts.md:36 +#: src/ch00/interacting/calling_other_contracts.md:38 msgid "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" "// We need to have the interface of the callee contract defined\n" "// so that we can import the Dispatcher.\n" -"#[starknet::interface]\n" -"trait ICallee {\n" -" fn set_value(ref self: TContractState, value: u128) -> u128;\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ICaller {\n" -" fn set_value_from_address(ref self: TContractState, addr: " -"ContractAddress, value: u128);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod Caller {\n" -" // We import the Dispatcher of the called contract\n" -" use super::{ICalleeDispatcher, ICalleeDispatcherTrait};\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ICallerImpl of super::ICaller {\n" -" fn set_value_from_address(ref self: ContractState, addr: " -"ContractAddress, value: u128) {\n" -" ICalleeDispatcher { contract_address: addr }.set_value(value);\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"// We need to have the interface of the callee contract defined\n" -"// so that we can import the Dispatcher.\n" -"#[starknet::interface]\n" -"trait ICallee {\n" -" fn set_value(ref self: TContractState, value: u128) -> u128;\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ICaller {\n" -" fn set_value_from_address(ref self: TContractState, addr: " -"ContractAddress, value: u128);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod Caller {\n" -" // We import the Dispatcher of the called contract\n" -" use super::{ICalleeDispatcher, ICalleeDispatcherTrait};\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ICallerImpl of super::ICaller {\n" -" fn set_value_from_address(ref self: ContractState, addr: " -"ContractAddress, value: u128) {\n" -" ICalleeDispatcher { contract_address: addr }.set_value(value);\n" -" }\n" -" }\n" -"}\n" -"```" + +#: src/ch00/interacting/calling_other_contracts.md:53 +msgid "// We import the Dispatcher of the called contract\n" +msgstr "" #: src/ch00/interacting/calling_other_contracts.md:68 msgid "" @@ -2654,7 +1462,8 @@ msgstr "" "cairo) 中尝试它。" #: src/ch00/interacting/factory.md:1 -msgid "# Factory Pattern" +#, fuzzy +msgid "Factory Pattern" msgstr "# 工厂模式" #: src/ch00/interacting/factory.md:3 @@ -2666,37 +1475,38 @@ msgstr "" #: src/ch00/interacting/factory.md:5 msgid "" -"In the case of smart contracts, we can use this pattern by defining a factory " -"contract that have the sole responsibility of creating and managing other " -"contracts." +"In the case of smart contracts, we can use this pattern by defining a " +"factory contract that have the sole responsibility of creating and managing " +"other contracts." msgstr "" -"在智能合约里,我们可以通过定义一个工厂合约来使用这种模式,该合约全权负责创建和" -"管理其他合约。" +"在智能合约里,我们可以通过定义一个工厂合约来使用这种模式,该合约全权负责创建" +"和管理其他合约。" #: src/ch00/interacting/factory.md:7 -msgid "## Class hash and contract instance" +#, fuzzy +msgid "Class hash and contract instance" msgstr "## 类哈希(Class hash)和合约实例" #: src/ch00/interacting/factory.md:9 msgid "" -"In Starknet, there's a separation between contract's classes and instances. A " -"contract class serves as a blueprint, defined by the underling Cairo " +"In Starknet, there's a separation between contract's classes and instances. " +"A contract class serves as a blueprint, defined by the underling Cairo " "bytecode, contract's entrypoints, ABI and Sierra program hash. The contract " "class is identified by a class hash. When you want to add a new class to the " "network, you first need to declare it." msgstr "" "在Starknet中,合约的类和实例是分开的。合约类充当蓝图,由底层 Cairo 字节码、合" -"约的入口点、ABI 和 Sierra 程序哈希定义。合约类由类哈希标识。当您想向网络添加一" -"个新类时,首先需要声明它。" +"约的入口点、ABI 和 Sierra 程序哈希定义。合约类由类哈希标识。当您想向网络添加" +"一个新类时,首先需要声明它。" #: src/ch00/interacting/factory.md:11 msgid "" -"When deploying a contract, you need to specify the class hash of the contract " -"you want to deploy. Each instance of a contract has their own storage " -"regardless of the class hash." +"When deploying a contract, you need to specify the class hash of the " +"contract you want to deploy. Each instance of a contract has their own " +"storage regardless of the class hash." msgstr "" -"部署合约时,需要指定要部署的合约的类哈希值。合约的每个实例都有自己的存储,这与" -"类哈希无关。" +"部署合约时,需要指定要部署的合约的类哈希值。合约的每个实例都有自己的存储,这" +"与类哈希无关。" #: src/ch00/interacting/factory.md:13 msgid "" @@ -2705,7 +1515,8 @@ msgid "" msgstr "使用工厂模式,我们可以部署同一合约类的多个实例,并轻松处理升级。" #: src/ch00/interacting/factory.md:15 -msgid "## Minimal example" +#, fuzzy +msgid "Minimal example" msgstr "## 最小范例" #: src/ch00/interacting/factory.md:17 @@ -2714,165 +1525,39 @@ msgid "" "`SimpleCounter` contract:" msgstr "下面是部署`SimpleCounter` 合约的工厂合约的最小范例:" -#: src/ch00/interacting/factory.md:19 -msgid "" -"```rust\n" -"use starknet::{ContractAddress, ClassHash};\n" -"\n" -"#[starknet::interface]\n" -"trait ICounterFactory {\n" -" /// Create a new counter contract from stored arguments\n" -" fn create_counter(ref self: TContractState) -> ContractAddress;\n" -"\n" -" /// Create a new counter contract from the given arguments\n" -" fn create_counter_at(ref self: TContractState, init_value: u128) -> " -"ContractAddress;\n" -"\n" -" /// Update the argument\n" -" fn update_init_value(ref self: TContractState, init_value: u128);\n" -"\n" -" /// Update the class hash of the Counter contract to deploy when creating " -"a new counter\n" -" fn update_counter_class_hash(ref self: TContractState, " -"counter_class_hash: ClassHash);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod CounterFactory {\n" -" use starknet::{ContractAddress, ClassHash};\n" -" use starknet::syscalls::deploy_syscall;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" /// Store the constructor arguments of the contract to deploy\n" -" init_value: u128,\n" -" /// Store the class hash of the contract to deploy\n" -" counter_class_hash: ClassHash,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, init_value: u128, class_hash: " -"ClassHash) {\n" -" self.init_value.write(init_value);\n" -" self.counter_class_hash.write(class_hash);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl Factory of super::ICounterFactory {\n" -" fn create_counter_at(ref self: ContractState, init_value: u128) -> " -"ContractAddress {\n" -" // Contructor arguments\n" -" let mut constructor_calldata: Array:: = array!" -"[init_value.into()];\n" -"\n" -" // Contract deployment\n" -" let (deployed_address, _) = deploy_syscall(\n" -" self.counter_class_hash.read(), 0, constructor_calldata." -"span(), false\n" -" )\n" -" .expect('failed to deploy counter');\n" -"\n" -" deployed_address\n" -" }\n" -"\n" -" fn create_counter(ref self: ContractState) -> ContractAddress {\n" -" self.create_counter_at(self.init_value.read())\n" -" }\n" -"\n" -" fn update_init_value(ref self: ContractState, init_value: u128) {\n" -" self.init_value.write(init_value);\n" -" }\n" -"\n" -" fn update_counter_class_hash(ref self: ContractState, " -"counter_class_hash: ClassHash) {\n" -" self.counter_class_hash.write(counter_class_hash);\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/ch00/interacting/factory.md:24 +msgid "/// Create a new counter contract from stored arguments\n" +msgstr "" + +#: src/ch00/interacting/factory.md:27 +msgid "/// Create a new counter contract from the given arguments\n" +msgstr "" + +#: src/ch00/interacting/factory.md:30 +msgid "/// Update the argument\n" msgstr "" -"```rust\n" -"use starknet::{ContractAddress, ClassHash};\n" -"\n" -"#[starknet::interface]\n" -"trait ICounterFactory {\n" -" /// Create a new counter contract from stored arguments\n" -" fn create_counter(ref self: TContractState) -> ContractAddress;\n" -"\n" -" /// Create a new counter contract from the given arguments\n" -" fn create_counter_at(ref self: TContractState, init_value: u128) -> " -"ContractAddress;\n" -"\n" -" /// Update the argument\n" -" fn update_init_value(ref self: TContractState, init_value: u128);\n" -"\n" -" /// Update the class hash of the Counter contract to deploy when creating " -"a new counter\n" -" fn update_counter_class_hash(ref self: TContractState, " -"counter_class_hash: ClassHash);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod CounterFactory {\n" -" use starknet::{ContractAddress, ClassHash};\n" -" use starknet::syscalls::deploy_syscall;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" /// Store the constructor arguments of the contract to deploy\n" -" init_value: u128,\n" -" /// Store the class hash of the contract to deploy\n" -" counter_class_hash: ClassHash,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, init_value: u128, class_hash: " -"ClassHash) {\n" -" self.init_value.write(init_value);\n" -" self.counter_class_hash.write(class_hash);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl Factory of super::ICounterFactory {\n" -" fn create_counter_at(ref self: ContractState, init_value: u128) -> " -"ContractAddress {\n" -" // Contructor arguments\n" -" let mut constructor_calldata: Array:: = array!" -"[init_value.into()];\n" -"\n" -" // Contract deployment\n" -" let (deployed_address, _) = deploy_syscall(\n" -" self.counter_class_hash.read(), 0, constructor_calldata." -"span(), false\n" -" )\n" -" .expect('failed to deploy counter');\n" -"\n" -" deployed_address\n" -" }\n" -"\n" -" fn create_counter(ref self: ContractState) -> ContractAddress {\n" -" self.create_counter_at(self.init_value.read())\n" -" }\n" -"\n" -" fn update_init_value(ref self: ContractState, init_value: u128) {\n" -" self.init_value.write(init_value);\n" -" }\n" -"\n" -" fn update_counter_class_hash(ref self: ContractState, " -"counter_class_hash: ClassHash) {\n" -" self.counter_class_hash.write(counter_class_hash);\n" -" }\n" -" }\n" -"}\n" -"```" -#: src/ch00/interacting/factory.md:86 +#: src/ch00/interacting/factory.md:33 msgid "" -"\n" -"\n" -"
Last change: 2023-10-19
" -msgstr "" -"\n" -"\n" -"
Last change: 2023-10-19
" - #: src/ch00/testing/contract-testing.md:1 -msgid "# Contract Testing" +#, fuzzy +msgid "Contract Testing" msgstr "# 合约测试" #: src/ch00/testing/contract-testing.md:3 @@ -2920,282 +1594,57 @@ msgid "" "contracts. In this section, we'll guide you through the basics of testing a " "smart contract on Starknet with `scarb`." msgstr "" -"测试在软件开发中起着至关重要的作用,尤其是对于智能合约而言。在本节中,我们将通" -"过Starknet上的`scarb` ,引导你了解智能合约测试的基础知识。" +"测试在软件开发中起着至关重要的作用,尤其是对于智能合约而言。在本节中,我们将" +"通过Starknet上的`scarb` ,引导你了解智能合约测试的基础知识。" #: src/ch00/testing/contract-testing.md:5 msgid "Let's start with a simple smart contract as an example:" msgstr "让我们以一个简单的智能合约作为例子开始:" -#: src/ch00/testing/contract-testing.md:6 -msgid "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait ISimpleContract {\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn get_owner(self: @TContractState) -> ContractAddress;\n" -" fn set_value(ref self: TContractState, value: u32);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleContract {\n" -" use starknet::{get_caller_address, ContractAddress};\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32,\n" -" owner: ContractAddress\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, initial_value: u32) {\n" -" self.value.write(initial_value);\n" -" self.owner.write(get_caller_address());\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleContract of super::ISimpleContract {\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" fn get_owner(self: @ContractState) -> ContractAddress {\n" -" self.owner.read()\n" -" }\n" -"\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" assert(self.owner.read() == get_caller_address(), 'Not owner');\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait ISimpleContract {\n" -" fn get_value(self: @TContractState) -> u32;\n" -" fn get_owner(self: @TContractState) -> ContractAddress;\n" -" fn set_value(ref self: TContractState, value: u32);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleContract {\n" -" use starknet::{get_caller_address, ContractAddress};\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" value: u32,\n" -" owner: ContractAddress\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, initial_value: u32) {\n" -" self.value.write(initial_value);\n" -" self.owner.write(get_caller_address());\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleContract of super::ISimpleContract {\n" -" fn get_value(self: @ContractState) -> u32 {\n" -" self.value.read()\n" -" }\n" -"\n" -" fn get_owner(self: @ContractState) -> ContractAddress {\n" -" self.owner.read()\n" -" }\n" -"\n" -" fn set_value(ref self: ContractState, value: u32) {\n" -" assert(self.owner.read() == get_caller_address(), ‘Not owner’);\n" -" self.value.write(value);\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch00/testing/contract-testing.md:50 msgid "Now, take a look at the tests for this contract:" msgstr "现在,让我们看一下这个合约的测试:" -#: src/ch00/testing/contract-testing.md:51 +#: src/ch00/testing/contract-testing.md:54 msgid "" -"```rust\n" -"#[cfg(test)]\n" -"mod tests {\n" -" // Import the interface and dispatcher to be able to interact with the " +"// Import the interface and dispatcher to be able to interact with the " "contract.\n" -" use sbe_testing::contract::{\n" -" ISimpleContract, SimpleContract, ISimpleContractDispatcher, " -"ISimpleContractDispatcherTrait\n" -" };\n" -"\n" -" // Import the deploy syscall to be able to deploy the contract.\n" -" use starknet::class_hash::Felt252TryIntoClassHash;\n" -" use starknet::{\n" -" deploy_syscall, ContractAddress, get_caller_address, " -"get_contract_address,\n" -" contract_address_const\n" -" };\n" -"\n" -" // Use starknet test utils to fake the transaction context.\n" -" use starknet::testing::{set_caller_address, set_contract_address};\n" -"\n" -" // Deploy the contract and return its dispatcher.\n" -" fn deploy(initial_value: u32) -> ISimpleContractDispatcher {\n" -" // Set up constructor arguments.\n" -" let mut calldata = ArrayTrait::new();\n" -" initial_value.serialize(ref calldata);\n" -"\n" -" // Declare and deploy\n" -" let (contract_address, _) = deploy_syscall(\n" -" SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata." -"span(), false\n" -" )\n" -" .unwrap();\n" -"\n" -" // Return the dispatcher.\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:59 +msgid "// Import the deploy syscall to be able to deploy the contract.\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:66 +msgid "// Use starknet test utils to fake the transaction context.\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:69 +msgid "// Deploy the contract and return its dispatcher.\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:71 +msgid "// Set up constructor arguments.\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:75 +msgid "// Declare and deploy\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:81 +msgid "" +"// Return the dispatcher.\n" " // The dispatcher allows to interact with the contract based on its " "interface.\n" -" ISimpleContractDispatcher { contract_address }\n" -" }\n" -"\n" -" #[test]\n" -" #[available_gas(2000000000)]\n" -" fn test_deploy() {\n" -" let initial_value: u32 = 10;\n" -" let contract = deploy(initial_value);\n" -"\n" -" assert(contract.get_value() == initial_value, 'wrong initial " -"value');\n" -" assert(contract.get_owner() == get_contract_address(), 'wrong " -"owner');\n" -" }\n" -"\n" -" #[test]\n" -" #[available_gas(2000000000)]\n" -" fn test_set_as_owner() {\n" -" // Fake the caller address to address 1\n" -" let owner = contract_address_const::<1>();\n" -" set_contract_address(owner);\n" -"\n" -" let contract = deploy(10);\n" -" assert(contract.get_owner() == owner, 'wrong owner');\n" -"\n" -" // Fake the contract address to address 1\n" -" set_contract_address(owner);\n" -" let new_value: u32 = 20;\n" -" contract.set_value(new_value);\n" -"\n" -" assert(contract.get_value() == new_value, 'wrong value');\n" -" }\n" -"\n" -" #[test]\n" -" #[should_panic]\n" -" #[available_gas(2000000000)]\n" -" fn test_set_not_owner() {\n" -" let owner = contract_address_const::<1>();\n" -" set_contract_address(owner);\n" -"\n" -" let contract = deploy(10);\n" -"\n" -" let not_owner = contract_address_const::<2>();\n" -" set_contract_address(not_owner);\n" -"\n" -" let new_value: u32 = 20;\n" -" contract.set_value(new_value);\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[cfg(test)]\n" -"mod tests {\n" -" // 导入接口和调度器,以便能够与合约进行交互\n" -" use sbe_testing::contract::{\n" -" ISimpleContract, SimpleContract, ISimpleContractDispatcher, " -"ISimpleContractDispatcherTrait\n" -" };\n" -"\n" -" //导入部署 deploy_syscall,以便能够部署合约\n" -" use starknet::class_hash::Felt252TryIntoClassHash;\n" -" use starknet::{\n" -" deploy_syscall, ContractAddress, get_caller_address, " -"get_contract_address,\n" -" contract_address_const\n" -" };\n" -"\n" -" // 使用 starknet 测试工具来模拟上下文交易\n" -" use starknet::testing::{set_caller_address, set_contract_address};\n" -"\n" -" // 部署合约并返回其调度器\n" -" fn deploy(initial_value: u32) -> ISimpleContractDispatcher {\n" -" // Set up constructor arguments.\n" -" let mut calldata = ArrayTrait::new();\n" -" initial_value.serialize(ref calldata);\n" -"\n" -" // 声明并部署合约\n" -" let (contract_address, _) = deploy_syscall(\n" -" SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata." -"span(), false\n" -" )\n" -" .unwrap();\n" -"\n" -" // 返回调度器\n" -" // 调度器允许根据合约的接口与其进行交互\n" -" ISimpleContractDispatcher { contract_address }\n" -" }\n" -"\n" -" #[test]\n" -" #[available_gas(2000000000)]\n" -" fn test_deploy() {\n" -" let initial_value: u32 = 10;\n" -" let contract = deploy(initial_value);\n" -"\n" -" assert(contract.get_value() == initial_value, ‘wrong initial " -"value’);\n" -" assert(contract.get_owner() == get_contract_address(), ‘wrong " -"owner’);\n" -" }\n" -"\n" -" #[test]\n" -" #[available_gas(2000000000)]\n" -" fn test_set_as_owner() {\n" -" // 将调用者地址设置为地址1\n" -" let owner = contract_address_const::<1>();\n" -" set_contract_address(owner);\n" -"\n" -" let contract = deploy(10);\n" -" assert(contract.get_owner() == owner, ‘wrong owner’);\n" -"\n" -" // 将合约地址设置为地址1\n" -" set_contract_address(owner);\n" -" let new_value: u32 = 20;\n" -" contract.set_value(new_value);\n" -"\n" -" assert(contract.get_value() == new_value, ‘wrong value’);\n" -" }\n" -"\n" -" #[test]\n" -" #[should_panic]\n" -" #[available_gas(2000000000)]\n" -" fn test_set_not_owner() {\n" -" let owner = contract_address_const::<1>();\n" -" set_contract_address(owner);\n" -"\n" -" let contract = deploy(10);\n" -"\n" -" let not_owner = contract_address_const::<2>();\n" -" set_contract_address(not_owner);\n" -"\n" -" let new_value: u32 = 20;\n" -" contract.set_value(new_value);\n" -" }\n" -"}\n" -"```" + +#: src/ch00/testing/contract-testing.md:99 +msgid "// Fake the caller address to address 1\n" +msgstr "" + +#: src/ch00/testing/contract-testing.md:106 +msgid "// Fake the contract address to address 1\n" +msgstr "" #: src/ch00/testing/contract-testing.md:132 msgid "" @@ -3209,20 +1658,20 @@ msgstr "" #: src/ch00/testing/contract-testing.md:134 msgid "" -"To define our test, we use scarb, which allows us to create a separate module " -"guarded with `#[cfg(test)]`. This ensures that the test module is only " -"compiled when running tests using `scarb test`." +"To define our test, we use scarb, which allows us to create a separate " +"module guarded with `#[cfg(test)]`. This ensures that the test module is " +"only compiled when running tests using `scarb test`." msgstr "" -"为了定义我们的测试,我们使用 scarb,它允许我们创建一个被 `#[cfg(test)]` 保护的" -"独立模块。这样可以确保测试模块只在使用 `scarb test` 运行测试时被编译。" +"为了定义我们的测试,我们使用 scarb,它允许我们创建一个被 `#[cfg(test)]` 保护" +"的独立模块。这样可以确保测试模块只在使用 `scarb test` 运行测试时被编译。" #: src/ch00/testing/contract-testing.md:136 msgid "" -"Each test is defined as a function with the `#[test]` attribute. You can also " -"check if a test panics using the `#[should_panic]` attribute." +"Each test is defined as a function with the `#[test]` attribute. You can " +"also check if a test panics using the `#[should_panic]` attribute." msgstr "" -"每个测试都被定义为带有 `#[test]` 属性的函数。您还可以使用 `#[should_panic]` 属" -"性检查测试是否会引发 panic。" +"每个测试都被定义为带有 `#[test]` 属性的函数。您还可以使用 `#[should_panic]` " +"属性检查测试是否会引发 panic。" #: src/ch00/testing/contract-testing.md:138 msgid "" @@ -3236,7 +1685,8 @@ msgstr "" "特定 gas 限制下的好方法!" #: src/ch00/testing/contract-testing.md:140 -msgid "> Note: The term \"gas\" here refers to Sierra gas, not L1 gas" +#, fuzzy +msgid "Note: The term \"gas\" here refers to Sierra gas, not L1 gas" msgstr "> 注意:这里的 “gas” 一词指的是 Sierra gas,而不是 L1 的 gas" #: src/ch00/testing/contract-testing.md:142 @@ -3244,9 +1694,16 @@ msgid "Now, let's move on to the testing process:" msgstr "现在,让我们进入测试过程:" #: src/ch00/testing/contract-testing.md:143 +#, fuzzy +msgid "Use the `deploy` function logic to declare and deploy your contract." +msgstr "" +"- 使用 `deploy` 函数的逻辑来声明和部署您的合约。\n" +"- 使用 `assert` 来验证合约在给定的上下文中的行为是否符合预期。" + +#: src/ch00/testing/contract-testing.md:144 +#, fuzzy msgid "" -"- Use the `deploy` function logic to declare and deploy your contract.\n" -"- Use `assert` to verify that the contract behaves as expected in the given " +"Use `assert` to verify that the contract behaves as expected in the given " "context." msgstr "" "- 使用 `deploy` 函数的逻辑来声明和部署您的合约。\n" @@ -3254,25 +1711,33 @@ msgstr "" #: src/ch00/testing/contract-testing.md:146 msgid "" -"To make testing more convenient, the `testing` module of the corelib provides " -"some helpful functions:" +"To make testing more convenient, the `testing` module of the corelib " +"provides some helpful functions:" msgstr "为了使测试更加方便,corelib 的 `testing` 模块提供了一些有用的函数:" #: src/ch00/testing/contract-testing.md:147 -msgid "" -"- `set_caller_address(address: ContractAddress)`\n" -"- `set_contract_address(address: ContractAddress)`\n" -"- `set_block_number(block_number: u64)`\n" -"- `set_block_timestamp(block_timestamp: u64)`\n" -"- `set_account_contract_address(address: ContractAddress)`\n" -"- `set_max_fee(fee: u128)`" +msgid "`set_caller_address(address: ContractAddress)`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:148 +msgid "`set_contract_address(address: ContractAddress)`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:149 +msgid "`set_block_number(block_number: u64)`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:150 +msgid "`set_block_timestamp(block_timestamp: u64)`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:151 +msgid "`set_account_contract_address(address: ContractAddress)`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:152 +msgid "`set_max_fee(fee: u128)`" msgstr "" -"- `set_caller_address(address: ContractAddress)`\n" -"- `set_contract_address(address: ContractAddress)`\n" -"- `set_block_number(block_number: u64)`\n" -"- `set_block_timestamp(block_timestamp: u64)`\n" -"- `set_account_contract_address(address: ContractAddress)`\n" -"- `set_max_fee(fee: u128)`" #: src/ch00/testing/contract-testing.md:154 msgid "" @@ -3282,50 +1747,56 @@ msgstr "" "你可能还需要 corelib 中的 `info` 模块,它允许你访问有关当前交易上下文的信息:" #: src/ch00/testing/contract-testing.md:155 -msgid "" -"- `get_caller_address() -> ContractAddress`\n" -"- `get_contract_address() -> ContractAddress`\n" -"- `get_block_info() -> Box`\n" -"- `get_tx_info() -> Box`\n" -"- `get_block_timestamp() -> u64`\n" -"- `get_block_number() -> u64`" +msgid "`get_caller_address() -> ContractAddress`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:156 +msgid "`get_contract_address() -> ContractAddress`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:157 +msgid "`get_block_info() -> Box`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:158 +msgid "`get_tx_info() -> Box`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:159 +msgid "`get_block_timestamp() -> u64`" +msgstr "" + +#: src/ch00/testing/contract-testing.md:160 +msgid "`get_block_number() -> u64`" msgstr "" -"- `get_caller_address() -> ContractAddress`\n" -"- `get_contract_address() -> ContractAddress`\n" -"- `get_block_info() -> Box`\n" -"- `get_tx_info() -> Box`\n" -"- `get_block_timestamp() -> u64`\n" -"- `get_block_number() -> u64`" #: src/ch00/testing/contract-testing.md:163 +#, fuzzy msgid "" "You can found the full list of functions in the [Starknet Corelib repo]" -"(https://github.com/starkware-libs/cairo/tree/main/corelib/src/starknet).\n" +"(https://github.com/starkware-libs/cairo/tree/main/corelib/src/starknet). " "You can also find a detailled explaination of testing in cairo in the [Cairo " "book - Chapter 8](https://book.cairo-lang.org/ch08-01-how-to-write-tests." "html)." msgstr "" -"你可以在 [Starknet Corelib 仓库](https://github.com/starkware-libs/cairo/tree/" -"main/corelib/src/starknet) 中找到完整的函数列表。\n" +"你可以在 [Starknet Corelib 仓库](https://github.com/starkware-libs/cairo/" +"tree/main/corelib/src/starknet) 中找到完整的函数列表。\n" "你还可以在 [Cairo book 第8章](https://book.cairo-lang.org/ch08-01-how-to-" "write-tests.html) 中找到有关在 cairo 中进行测试的详细说明。" #: src/ch00/testing/contract-testing.md:166 -msgid "## Starknet Foundry" +#, fuzzy +msgid "Starknet Foundry" msgstr "## Starknet Foundry" -#: src/ch00/testing/contract-testing.md:168 -msgid "" -msgstr "" - #: src/ch00/testing/contract-testing.md:170 msgid "" "Starknet Foundry is a powerful toolkit for developing smart contracts on " "Starknet. It offers support for testing Starknet smart contracts on top of " "`scarb` with the `Forge` tool." msgstr "" -"Starknet Foundry是在Starknet上开发智能合约的强大工具包。它提供了对使用`Forge` " -"工具在 `scarb` 上测试Starknet智能合约的支持。" +"Starknet Foundry是在Starknet上开发智能合约的强大工具包。它提供了对使用" +"`Forge` 工具在 `scarb` 上测试Starknet智能合约的支持。" #: src/ch00/testing/contract-testing.md:172 msgid "" @@ -3335,8 +1806,8 @@ msgid "" "Starknet Foundry and incorporating it into your projects." msgstr "" "使用 `snforge` 进行测试与我们刚刚描述的过程类似,但更简化。此外,还有其他功能" -"正在开发中,包括作弊码或并行测试执行。我们强烈推荐探索Starknet Foundry并将其纳" -"入您你的项目中。" +"正在开发中,包括作弊码或并行测试执行。我们强烈推荐探索Starknet Foundry并将其" +"纳入您你的项目中。" #: src/ch00/testing/contract-testing.md:174 msgid "" @@ -3349,7 +1820,8 @@ msgstr "" "html)。" #: src/ch00/cairo_cheatsheet/cairo_cheatsheet.md:1 -msgid "# Cairo Cheatsheet" +#, fuzzy +msgid "Cairo Cheatsheet" msgstr "# Cairo 备忘单" #: src/ch00/cairo_cheatsheet/cairo_cheatsheet.md:3 @@ -3358,23 +1830,17 @@ msgid "" "constructs." msgstr "本章旨在为最常见的Cairo结构提供快速参考。" -#: src/ch00/cairo_cheatsheet/cairo_cheatsheet.md:5 -#: src/ch00/cairo_cheatsheet/mapping.md:58 -#: src/ch00/cairo_cheatsheet/arrays.md:42 src/ch00/cairo_cheatsheet/match.md:59 -#: src/ch00/cairo_cheatsheet/struct.md:15 -msgid "
Last change: 2023-10-31
" -msgstr "
Last change: 2023-10-31
" - #: src/ch00/cairo_cheatsheet/felt.md:1 -msgid "# Felt252" +#, fuzzy +msgid "Felt252" msgstr "# Felt252" #: src/ch00/cairo_cheatsheet/felt.md:3 +#, fuzzy msgid "" "Felt252 is a fundamental data type in Cairo from which all other data types " -"are derived.\n" -"Felt252 can also be used to store short-string representations with a maximum " -"length of 31 characters." +"are derived. Felt252 can also be used to store short-string representations " +"with a maximum length of 31 characters." msgstr "" "Felt252是Cairo中的基本数据类型,所有其他数据类型都派生自它。\n" "Felt252也可以用于存储最多31个字符长度的短字符串表示。" @@ -3384,608 +1850,175 @@ msgstr "" msgid "For example:" msgstr "例如:" -#: src/ch00/cairo_cheatsheet/felt.md:8 -msgid "" -"```rust\n" -" let felt: felt252 = 100;\n" -" let felt_as_str = 'Hello Starknet!';\n" -"\n" -" let felt = felt + felt_as_str;\n" -"```" -msgstr "" -"```rust\n" -" let felt: felt252 = 100;\n" -" let felt_as_str = ‘Hello Starknet!’;\n" -"\n" -" let felt = felt + felt_as_str;\n" -"```" - #: src/ch00/cairo_cheatsheet/mapping.md:1 -msgid "# Mapping" -msgstr "# Mapping" +#, fuzzy +msgid "Mapping" +msgstr "映射" #: src/ch00/cairo_cheatsheet/mapping.md:3 +#, fuzzy msgid "" -"The ```LegacyMap``` type can be used to represent a collection of key-value." +"The `LegacyMap` type can be used to represent a collection of key-value." msgstr "`LegacyMap` 类型可以用于表示键值对的集合。" -#: src/ch00/cairo_cheatsheet/mapping.md:5 +#: src/ch00/cairo_cheatsheet/mapping.md:51 msgid "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IMappingExample {\n" -" fn register_user(ref self: TContractState, student_add: ContractAddress, " -"studentName: felt252);\n" -" fn record_student_score(\n" -" ref self: TContractState, student_add: ContractAddress, subject: " -"felt252, score: u16\n" -" );\n" -" fn view_student_name(self: @TContractState, student_add: ContractAddress) " -"-> felt252;\n" -" fn view_student_score(\n" -" self: @TContractState, student_add: ContractAddress, subject: " -"felt252\n" -" ) -> u16;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod MappingContract {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" students_name: LegacyMap::,\n" -" students_result_record: LegacyMap::<(ContractAddress, felt252), " -"u16>,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl External of super::IMappingExample {\n" -" fn register_user(\n" -" ref self: ContractState, student_add: ContractAddress, " -"studentName: felt252\n" -" ) {\n" -" self.students_name.write(student_add, studentName);\n" -" }\n" -"\n" -" fn record_student_score(\n" -" ref self: ContractState, student_add: ContractAddress, subject: " -"felt252, score: u16\n" -" ) {\n" -" self.students_result_record.write((student_add, subject), " -"score);\n" -" }\n" -"\n" -" fn view_student_name(self: @ContractState, student_add: " -"ContractAddress) -> felt252 {\n" -" self.students_name.read(student_add)\n" -" }\n" -"\n" -" fn view_student_score(\n" -" self: @ContractState, student_add: ContractAddress, subject: " -"felt252\n" -" ) -> u16 {\n" -" // for a 2D mapping its important to take note of the amount of " -"brackets being used.\n" -" self.students_result_record.read((student_add, subject))\n" -" }\n" -" }\n" -"}\n" -"```" +"// for a 2D mapping its important to take note of the amount of brackets " +"being used.\n" msgstr "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IMappingExample {\n" -" fn register_user(ref self: TContractState, student_add: ContractAddress, " -"studentName: felt252);\n" -" fn record_student_score(\n" -" ref self: TContractState, student_add: ContractAddress, subject: " -"felt252, score: u16\n" -" );\n" -" fn view_student_name(self: @TContractState, student_add: ContractAddress) " -"-> felt252;\n" -" fn view_student_score(\n" -" self: @TContractState, student_add: ContractAddress, subject: " -"felt252\n" -" ) -> u16;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod MappingContract {\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" students_name: LegacyMap::,\n" -" students_result_record: LegacyMap::<(ContractAddress, felt252), " -"u16>,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl External of super::IMappingExample {\n" -" fn register_user(\n" -" ref self: ContractState, student_add: ContractAddress, " -"studentName: felt252\n" -" ) {\n" -" self.students_name.write(student_add, studentName);\n" -" }\n" -"\n" -" fn record_student_score(\n" -" ref self: ContractState, student_add: ContractAddress, subject: " -"felt252, score: u16\n" -" ) {\n" -" self.students_result_record.write((student_add, subject), " -"score);\n" -" }\n" -"\n" -" fn view_student_name(self: @ContractState, student_add: " -"ContractAddress) -> felt252 {\n" -" self.students_name.read(student_add)\n" -" }\n" -"\n" -" fn view_student_score(\n" -" self: @ContractState, student_add: ContractAddress, subject: " -"felt252\n" -" ) -> u16 {\n" -" // 对于二维映射,重要的是注意使用的括号数量。\n" -" self.students_result_record.read((student_add, subject))\n" -" }\n" -" }\n" -"}\n" -"```" - -#: src/ch00/cairo_cheatsheet/arrays.md:1 -msgid "# Arrays" -msgstr "# 数组" #: src/ch00/cairo_cheatsheet/arrays.md:3 +#, fuzzy msgid "" -"Arrays are collections of elements of the same type.\n" -"The possible operations on arrays are defined with the `array::ArrayTrait` of " -"the corelib:" +"Arrays are collections of elements of the same type. The possible operations " +"on arrays are defined with the `array::ArrayTrait` of the corelib:" msgstr "" "数组是相同类型元素的集合。\n" "可以使用 corelib 的 `array::ArrayTrait` 来定义可能的数组操作:" -#: src/ch00/cairo_cheatsheet/arrays.md:6 -msgid "" -"```rust\n" -"trait ArrayTrait {\n" -" fn new() -> Array;\n" -" fn append(ref self: Array, value: T);\n" -" fn pop_front(ref self: Array) -> Option nopanic;\n" -" fn pop_front_consume(self: Array) -> Option<(Array, T)> nopanic;\n" -" fn get(self: @Array, index: usize) -> Option>;\n" -" fn at(self: @Array, index: usize) -> @T;\n" -" fn len(self: @Array) -> usize;\n" -" fn is_empty(self: @Array) -> bool;\n" -" fn span(self: @Array) -> Span;\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"trait ArrayTrait {\n" -" fn new() -> Array;\n" -" fn append(ref self: Array, value: T);\n" -" fn pop_front(ref self: Array) -> Option nopanic;\n" -" fn pop_front_consume(self: Array) -> Option<(Array, T)> nopanic;\n" -" fn get(self: @Array, index: usize) -> Option>;\n" -" fn at(self: @Array, index: usize) -> @T;\n" -" fn len(self: @Array) -> usize;\n" -" fn is_empty(self: @Array) -> bool;\n" -" fn span(self: @Array) -> Span;\n" -"}\n" -"```" - -#: src/ch00/cairo_cheatsheet/arrays.md:22 -msgid "" -"```rust\n" -"fn array() -> bool {\n" -" let mut arr = ArrayTrait::::new();\n" -" arr.append(10);\n" -" arr.append(20);\n" -" arr.append(30);\n" -"\n" -" assert(arr.len() == 3, 'array length should be 3');\n" -"\n" -" let first_value = arr.pop_front().unwrap();\n" -" assert(first_value == 10, 'first value should match');\n" -"\n" -" let second_value = *arr.at(0);\n" -" assert(second_value == 20, 'second value should match');\n" -"\n" -" // Returns true if an array is empty, then false if it isn't.\n" -" arr.is_empty()\n" -"}\n" -"```" +#: src/ch00/cairo_cheatsheet/arrays.md:37 +msgid "// Returns true if an array is empty, then false if it isn't.\n" msgstr "" -"```rust\n" -"fn array() -> bool {\n" -" let mut arr = ArrayTrait::::new();\n" -" arr.append(10);\n" -" arr.append(20);\n" -" arr.append(30);\n" -"\n" -" assert(arr.len() == 3, ‘array length should be 3’);\n" -"\n" -" let first_value = arr.pop_front().unwrap();\n" -" assert(first_value == 10, ‘first value should match’);\n" -"\n" -" let second_value = *arr.at(0);\n" -" assert(second_value == 20, ‘second value should match’);\n" -"\n" -" // 如果数组为空,返回 true;如果不为空,返回 false。\n" -" arr.is_empty()\n" -"}\n" -"```" - -#: src/ch00/cairo_cheatsheet/loop.md:1 -msgid "# Loop" -msgstr "# 循环" #: src/ch00/cairo_cheatsheet/loop.md:3 +#, fuzzy msgid "" "A loop specifies a block of code that will run repetitively until a halting " -"condition is encountered.\n" -"For example:" +"condition is encountered. For example:" msgstr "" "循环指定一个代码块,该代码块将重复运行,直到遇到停止条件。\n" "例如:" -#: src/ch00/cairo_cheatsheet/loop.md:6 -msgid "" -"```rust\n" -" let mut arr = ArrayTrait::new();\n" -"\n" -" // Same as ~ while (i < 10) arr.append(i++);\n" -" let mut i: u32 = 0;\n" -" let limit = 10;\n" -" loop {\n" -" if i == limit {\n" -" break;\n" -" };\n" -"\n" -" arr.append(i);\n" -"\n" -" i += 1;\n" -" };\n" -"```" +#: src/ch00/cairo_cheatsheet/loop.md:9 +msgid "// Same as ~ while (i < 10) arr.append(i++);\n" msgstr "" -"```rust\n" -" let mut arr = ArrayTrait::new();\n" -"\n" -" // 与 ~ while (i < 10) arr.append(i++); 相同\n" -" let mut i: u32 = 0;\n" -" let limit = 10;\n" -" loop {\n" -" if i == limit {\n" -" break;\n" -" };\n" -"\n" -" arr.append(i);\n" -"\n" -" i += 1;\n" -" };\n" -"```" - -#: src/ch00/cairo_cheatsheet/match.md:1 -msgid "# Match" -msgstr "# 分支" #: src/ch00/cairo_cheatsheet/match.md:3 +#, fuzzy msgid "" "The \"match\" expression in Cairo allows us to control the flow of our code " "by comparing a felt data type or an enum against various patterns and then " -"running specific code based on the pattern that matches.\n" -"For example:" +"running specific code based on the pattern that matches. For example:" msgstr "" "在 Cairo 中,”match” 表达式允许我们通过将 felt 数据类型或枚举与各种模式进行比" "较,然后根据匹配的模式运行特定的代码来控制代码的流程。例如:" -#: src/ch00/cairo_cheatsheet/match.md:6 +#: src/ch00/cairo_cheatsheet/tuples.md:3 +#, fuzzy msgid "" -"```rust\n" -"#[derive(Drop, Serde)]\n" -"enum Colour {\n" -" Red,\n" -" Blue,\n" -" Green,\n" -" Orange,\n" -" Black\n" -"}\n" -"\n" -"#[derive(Drop, Serde)]\n" -"enum Coin {\n" -" Penny,\n" -" Nickel,\n" -" Dime,\n" -" Quarter,\n" -"}\n" -"\n" -"fn value_in_cents(coin: Coin) -> felt252 {\n" -" match coin {\n" -" Coin::Penny => 1,\n" -" Coin::Nickel => 5,\n" -" Coin::Dime => 10,\n" -" Coin::Quarter => 25,\n" -" }\n" -"}\n" -"\n" -"fn specified_colour(colour: Colour) -> felt252 {\n" -" let mut response: felt252 = '';\n" -"\n" -" match colour {\n" -" Colour::Red => { response = 'You passed in Red'; },\n" -" Colour::Blue => { response = 'You passed in Blue'; },\n" -" Colour::Green => { response = 'You passed in Green'; },\n" -" Colour::Orange => { response = 'You passed in Orange'; },\n" -" Colour::Black => { response = 'You passed in Black'; },\n" -" };\n" -"\n" -" response\n" -"}\n" -"\n" -"fn quiz(num: felt252) -> felt252 {\n" -" let mut response: felt252 = '';\n" -"\n" -" match num {\n" -" 0 => { response = 'You failed' },\n" -" _ => { response = 'You Passed' },\n" -" };\n" -"\n" -" response\n" -"}\n" -"```" +"Tuples is a data type to group a fixed number of items of potentially " +"different types into a single compound structure. Unlike arrays, tuples have " +"a set length and can contain elements of varying types. Once a tuple is " +"created, its size cannot change. For example:" msgstr "" -"```rust\n" -"#[derive(Drop, Serde)]\n" -"enum Colour {\n" -" Red,\n" -" Blue,\n" -" Green,\n" -" Orange,\n" -" Black\n" -"}\n" -"\n" -"#[derive(Drop, Serde)]\n" -"enum Coin {\n" -" Penny,\n" -" Nickel,\n" -" Dime,\n" -" Quarter,\n" -"}\n" -"\n" -"fn value_in_cents(coin: Coin) -> felt252 {\n" -" match coin {\n" -" Coin::Penny => 1,\n" -" Coin::Nickel => 5,\n" -" Coin::Dime => 10,\n" -" Coin::Quarter => 25,\n" -" }\n" -"}\n" -"\n" -"fn specified_colour(colour: Colour) -> felt252 {\n" -" let mut response: felt252 = ‘’;\n" -"\n" -" match colour {\n" -" Colour::Red => { response = ‘You passed in Red’; },\n" -" Colour::Blue => { response = ‘You passed in Blue’; },\n" -" Colour::Green => { response = ‘You passed in Green’; },\n" -" Colour::Orange => { response = ‘You passed in Orange’; },\n" -" Colour::Black => { response = ‘You passed in Black’; },\n" -" };\n" -"\n" -" response\n" -"}\n" -"\n" -"fn quiz(num: felt252) -> felt252 {\n" -" let mut response: felt252 = ‘’;\n" -"\n" -" match num {\n" -" 0 => { response = ‘You failed’ },\n" -" _ => { response = ‘You Passed’ },\n" -" };\n" -"\n" -" response\n" -"}\n" -"```" - -#: src/ch00/cairo_cheatsheet/tuples.md:1 -msgid "# Tuples" -msgstr "# 元组" +"元组是一种数据类型,用于将固定数量的不同类型的项组合成一个单一的复合结构。与" +"数组不同,元组具有固定的长度,并且可以包含不同类型的元素。一旦创建了元组,其" +"大小就无法更改。\n" +"例如:" -#: src/ch00/cairo_cheatsheet/tuples.md:3 -msgid "" -"Tuples is a data type to group a fixed number of items of potentially " -"different types into a single compound structure. Unlike arrays, tuples have " -"a set length and can contain elements of varying types. Once a tuple is " -"created, its size cannot change.\n" -"For example:" +#: src/ch00/cairo_cheatsheet/tuples.md:7 +msgid "\"0x000\"" msgstr "" -"元组是一种数据类型,用于将固定数量的不同类型的项组合成一个单一的复合结构。与数" -"组不同,元组具有固定的长度,并且可以包含不同类型的元素。一旦创建了元组,其大小" -"就无法更改。\n" -"例如:" -#: src/ch00/cairo_cheatsheet/tuples.md:6 -msgid "" -"```rust\n" -" let address = \"0x000\";\n" -" let age = 20;\n" -" let active = true;\n" -"\n" -" // Create tuple\n" -" let user_tuple = (address, age, active);\n" -"\n" -" // Access tuple\n" -" let (address, age, active) = stored_tuple;\n" -"```" +#: src/ch00/cairo_cheatsheet/tuples.md:11 +msgid "// Create tuple\n" msgstr "" -"```rust\n" -" let address = “0x000”;\n" -" let age = 20;\n" -" let active = true;\n" -"\n" -" // Create tuple\n" -" let user_tuple = (address, age, active);\n" -"\n" -" // Access tuple\n" -" let (address, age, active) = stored_tuple;\n" -"```" -#: src/ch00/cairo_cheatsheet/struct.md:1 -msgid "# Struct" -msgstr "# 结构体" +#: src/ch00/cairo_cheatsheet/tuples.md:14 +msgid "// Access tuple\n" +msgstr "" #: src/ch00/cairo_cheatsheet/struct.md:3 +#, fuzzy msgid "" "A struct is a data type similar to tuple. Like tuples they can be used to " -"hold data of different types.\n" -"For example:" +"hold data of different types. For example:" msgstr "" "结构体是一种类似于元组的数据类型。与元组类似,它们可以用于保存不同类型的数" "据。\n" "例如:" -#: src/ch00/cairo_cheatsheet/struct.md:6 +#: src/ch00/cairo_cheatsheet/struct.md:7 msgid "" -"```rust\n" "// With Store, you can store Data's structs in the storage part of " "contracts.\n" -"#[derive(Drop, starknet::Store)]\n" -"struct Data {\n" -" address: starknet::ContractAddress,\n" -" age: u8\n" -"}\n" -"```" msgstr "" -"```rust\n" -"// 使用 Store,您可以将 Data 结构体存储在合约的存储部分。\n" -"#[derive(Drop, starknet::Store)]\n" -"struct Data {\n" -" address: starknet::ContractAddress,\n" -" age: u8\n" -"}\n" -"```" - -#: src/ch00/cairo_cheatsheet/type_casting.md:1 -msgid "# Type casting" -msgstr "# 类型转换" #: src/ch00/cairo_cheatsheet/type_casting.md:3 +#, fuzzy msgid "" "Cairo supports the conversion from one scalar types to another by using the " -"into and try_into methods.\n" -"`traits::Into` is used for conversion from a smaller data type to a larger " -"data type, while `traits::TryInto` is used when converting from a larger to a " -"smaller type that might not fit. \n" -"For example:" +"into and try_into methods. `traits::Into` is used for conversion from a " +"smaller data type to a larger data type, while `traits::TryInto` is used " +"when converting from a larger to a smaller type that might not fit. For " +"example:" msgstr "" "Cairo支持使用into和try_into方法将一个标量类型转换为另一个类型。\n" -"`traits::Into` 用于从较小的数据类型转换为较大的数据类型,而 `traits::TryInto` " -"用于从较大的数据类型转换为较小的数据类型,可能会发生溢出的情况。\n" +"`traits::Into` 用于从较小的数据类型转换为较大的数据类型,而 `traits::" +"TryInto` 用于从较大的数据类型转换为较小的数据类型,可能会发生溢出的情况。\n" "例如:" -#: src/ch00/cairo_cheatsheet/type_casting.md:7 +#: src/ch00/cairo_cheatsheet/type_casting.md:11 msgid "" -"```rust\n" -" let a_number: u32 = 15;\n" -" let my_felt252 = 15;\n" -"\n" -" // Since a u32 might not fit in a u8 and a u16, we need to use try_into,\n" +"// Since a u32 might not fit in a u8 and a u16, we need to use try_into,\n" " // then unwrap the Option type thats returned.\n" -" let new_u8: u8 = a_number.try_into().unwrap();\n" -" let new_u16: u16 = a_number.try_into().unwrap();\n" -"\n" -" // since new_u32 is the of the same type (u32) as rand_number, we can " +msgstr "" + +#: src/ch00/cairo_cheatsheet/type_casting.md:16 +msgid "" +"// since new_u32 is the of the same type (u32) as rand_number, we can " "directly assign them,\n" " // or use the .into() method.\n" -" let new_u32: u32 = a_number;\n" -"\n" -" // When typecasting from a smaller size to an equal or larger size we use " +msgstr "" + +#: src/ch00/cairo_cheatsheet/type_casting.md:20 +msgid "" +"// When typecasting from a smaller size to an equal or larger size we use " "the .into() method.\n" " // Note: u64 and u128 are larger than u32, so a u32 type will always fit " "into them.\n" -" let new_u64: u64 = a_number.into();\n" -" let new_u128: u128 = a_number.into();\n" -"\n" -" // Since a felt252 is smaller than a u256, we can use the into() method\n" -" let new_u256: u256 = my_felt252.into();\n" -" let new_felt252: felt252 = new_u16.into();\n" -"\n" -" //note a usize is smaller than a felt so we use the try_into\n" -" let new_usize: usize = my_felt252.try_into().unwrap();\n" -"```" msgstr "" -"```rust\n" -" let a_number: u32 = 15;\n" -" let my_felt252 = 15;\n" -"\n" -" // 由于 u32 可能不匹配 u8 和 u16,我们需要使用 try_into\n" -" // 然后解包返回的 Option 类型。\n" -" let new_u8: u8 = a_number.try_into().unwrap();\n" -" let new_u16: u16 = a_number.try_into().unwrap();\n" -"\n" -" // 由于 new_u32 的类型(u32)与 a_number 相同,我们可以直接赋值\n" -" // 或使用 .into() 方法\n" -" let new_u32: u32 = a_number;\n" -"\n" -" // 当从较小的大小类型强制转换为相等或较大的大小类型时,我们使用 .into() 方" -"法\n" -" // 注意:u64 和 u128 大于 u32,所以 u32 类型将始终适合其中\n" -" let new_u64: u64 = a_number.into();\n" -" let new_u128: u128 = a_number.into();\n" -"\n" -" // 由于 felt252 比 u256 小,我们可以使用 into() 方法\n" -" let new_u256: u256 = my_felt252.into();\n" -" let new_felt252: felt252 = new_u16.into();\n" -"\n" -" //注意,usize 比 felt252 小,因此我们使用 try_into\n" -" let new_usize: usize = my_felt252.try_into().unwrap();\n" -"```" -#: src/ch01/upgradeable_contract.md:1 -msgid "# Upgradeable Contract" -msgstr "# 可升级合约" +#: src/ch00/cairo_cheatsheet/type_casting.md:25 +msgid "" +"// Since a felt252 is smaller than a u256, we can use the into() method\n" +msgstr "" + +#: src/ch00/cairo_cheatsheet/type_casting.md:29 +msgid "//note a usize is smaller than a felt so we use the try_into\n" +msgstr "" #: src/ch01/upgradeable_contract.md:3 +#, fuzzy msgid "" "In Starknet, contracts are divided into two parts: contract classes and " -"contract\n" -"instances. This division follows a similar concept used in object-oriented\n" -"programming languages, where we distinguish between the definition and " -"implementation\n" -"of objects." +"contract instances. This division follows a similar concept used in object-" +"oriented programming languages, where we distinguish between the definition " +"and implementation of objects." msgstr "" "在Starknet中,合约分为两个部分:合约类和合约实例。\n" "这种划分遵循了面向对象编程语言中的类和实例的概念。\n" "这样,我们区分了对象的定义和实现。" #: src/ch01/upgradeable_contract.md:8 +#, fuzzy msgid "" "A contract class is the definition of a contract: it specifies how the " -"contract\n" -"behaves. It contains essential information like the Cairo byte code, hint\n" -"information, entry point names, and everything that defines its semantics\n" -"unambiguously." +"contract behaves. It contains essential information like the Cairo byte " +"code, hint information, entry point names, and everything that defines its " +"semantics unambiguously." msgstr "" "合约类是合约的定义:它指定了合约的行为方式。\n" "合约类包含了关键信息,如Cairo字节码、提示信息、入口点名称等,\n" "以及一切明确定义合约类语义的内容。" #: src/ch01/upgradeable_contract.md:13 +#, fuzzy msgid "" "To identify different contract classes, Starknet assigns a unique identifier " -"to each\n" -"class: the class hash. A contract instance is a deployed contract that " -"corresponds to\n" -"a specific contract class. Think of it as an instance of an object in " -"languages like\n" -"Java." +"to each class: the class hash. A contract instance is a deployed contract " +"that corresponds to a specific contract class. Think of it as an instance of " +"an object in languages like Java." msgstr "" "为了识别不同的合约类,Starknet为每个类分配一个唯一的标识符:类哈希。\n" "合约实例是对应于特定合约类的已部署合约。\n" @@ -3997,8 +2030,8 @@ msgid "" "name in an object-oriented programming language. A contract instance is a " "deployed contract corresponding to a class." msgstr "" -"每个类由其类哈希值标识,类似于面向对象编程语言中的类名。合约实例是对应于某个类" -"的已部署合约。" +"每个类由其类哈希值标识,类似于面向对象编程语言中的类名。合约实例是对应于某个" +"类的已部署合约。" #: src/ch01/upgradeable_contract.md:20 msgid "" @@ -4009,117 +2042,26 @@ msgid "" "the data stored in the contract will remain the same." msgstr "" "当调用`replace_class_syscall`函数,你可以将已部署的合约升级到更新的版本。通过" -"使用这个函数,你可以更新与已部署合约相关联的类哈希,从而有效地升级合约的实现。" -"然而,这不会修改合约中的存储,因此合约中存储的所有数据将保持不变。" +"使用这个函数,你可以更新与已部署合约相关联的类哈希,从而有效地升级合约的实" +"现。然而,这不会修改合约中的存储,因此合约中存储的所有数据将保持不变。" #: src/ch01/upgradeable_contract.md:22 +#, fuzzy msgid "" "To illustrate this concept, let's consider an example with two contracts: " -"`UpgradeableContract_V0`, and `UpgradeableContract_V1`.\n" -"Start by deploying `UpgradeableContract_V0` as the initial version. Next, " -"send a transaction that invokes the `upgrade` function, with the class hash " -"of `UpgradeableContract_V1` as parameter to upgrade the class hash of the " +"`UpgradeableContract_V0`, and `UpgradeableContract_V1`. Start by deploying " +"`UpgradeableContract_V0` as the initial version. Next, send a transaction " +"that invokes the `upgrade` function, with the class hash of " +"`UpgradeableContract_V1` as parameter to upgrade the class hash of the " "deployed contract to the `UpgradeableContract_V1` one. Then, call the " -"`version` method on the contract to see that the contract was upgraded to the " -"V1 version." +"`version` method on the contract to see that the contract was upgraded to " +"the V1 version." msgstr "" "为了说明这个概念,让我们以两个合约为例:`UpgradeableContract_V0`和" "`UpgradeableContract_V1`。\n" "首先,部署`UpgradeableContract_V0`作为初始版本。接下来,发送一个调用`upgrade`" -"函数的交易,将部署合约的类哈希升级为`UpgradeableContract_V1`的类哈希。然后,调" -"用合约上的`version`方法,查看合约是否已升级到V1版本。" - -#: src/ch01/upgradeable_contract.md:25 -msgid "" -"```rust\n" -"use starknet::class_hash::ClassHash;\n" -"\n" -"#[starknet::interface]\n" -"trait IUpgradeableContract {\n" -" fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" -" fn version(self: @TContractState) -> u8;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod UpgradeableContract_V0 {\n" -" use starknet::class_hash::ClassHash;\n" -" use starknet::SyscallResultTrait;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Upgraded: Upgraded\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Upgraded {\n" -" implementation: ClassHash\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl UpgradeableContract of super::IUpgradeableContract {\n" -" fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" -" assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" -" starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" -" self.emit(Event::Upgraded(Upgraded { implementation: " -"impl_hash }))\n" -" }\n" -"\n" -" fn version(self: @ContractState) -> u8 {\n" -" 0\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"use starknet::class_hash::ClassHash;\n" -"\n" -"#[starknet::interface]\n" -"trait IUpgradeableContract {\n" -" fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" -" fn version(self: @TContractState) -> u8;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod UpgradeableContract_V0 {\n" -" use starknet::class_hash::ClassHash;\n" -" use starknet::SyscallResultTrait;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Upgraded: Upgraded\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Upgraded {\n" -" implementation: ClassHash\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl UpgradeableContract of super::IUpgradeableContract {\n" -" fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" -" assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" -" starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" -" self.emit(Event::Upgraded(Upgraded { implementation: " -"impl_hash }))\n" -" }\n" -"\n" -" fn version(self: @ContractState) -> u8 {\n" -" 0\n" -" }\n" -" }\n" -"}\n" -"```" +"函数的交易,将部署合约的类哈希升级为`UpgradeableContract_V1`的类哈希。然后," +"调用合约上的`version`方法,查看合约是否已升级到V1版本。" #: src/ch01/upgradeable_contract.md:68 msgid "" @@ -4137,98 +2079,6 @@ msgstr "" "blob/main/listings/ch01-applications/upgradeable_contract/src/" "upgradeable_contract_v0.cairo)中尝试它 。" -#: src/ch01/upgradeable_contract.md:71 -msgid "" -"```rust\n" -"use starknet::class_hash::ClassHash;\n" -"\n" -"#[starknet::interface]\n" -"trait IUpgradeableContract {\n" -" fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" -" fn version(self: @TContractState) -> u8;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod UpgradeableContract_V1 {\n" -" use starknet::class_hash::ClassHash;\n" -" use starknet::SyscallResultTrait;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Upgraded: Upgraded\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Upgraded {\n" -" implementation: ClassHash\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl UpgradeableContract of super::IUpgradeableContract {\n" -" fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" -" assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" -" starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" -" self.emit(Event::Upgraded(Upgraded { implementation: " -"impl_hash }))\n" -" }\n" -"\n" -" fn version(self: @ContractState) -> u8 {\n" -" 1\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"use starknet::class_hash::ClassHash;\n" -"\n" -"#[starknet::interface]\n" -"trait IUpgradeableContract {\n" -" fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" -" fn version(self: @TContractState) -> u8;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod UpgradeableContract_V1 {\n" -" use starknet::class_hash::ClassHash;\n" -" use starknet::SyscallResultTrait;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Upgraded: Upgraded\n" -" }\n" -"\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Upgraded {\n" -" implementation: ClassHash\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl UpgradeableContract of super::IUpgradeableContract {\n" -" fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" -" assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" -" starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" -" self.emit(Event::Upgraded(Upgraded { implementation: " -"impl_hash }))\n" -" }\n" -"\n" -" fn version(self: @ContractState) -> u8 {\n" -" 1\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch01/upgradeable_contract.md:114 msgid "" "Visit contract on [Voyager](https://goerli.voyager.online/" @@ -4246,25 +2096,30 @@ msgstr "" "upgradeable_contract_v1.cairo) 中尝试它。" #: src/ch01/simple_vault.md:1 -msgid "# Simple Defi Vault" +#, fuzzy +msgid "Simple Defi Vault" msgstr "# 简单的去中心化金融保险库" #: src/ch01/simple_vault.md:3 +#, fuzzy msgid "" "This is the Cairo adaptation of the [Solidity by example Vault](https://" -"solidity-by-example.org/defi/vault/).\n" -"Here's how it works:" +"solidity-by-example.org/defi/vault/). Here's how it works:" msgstr "" -"这是 [Solidity by example Vault](https://solidity-by-example.org/defi/vault/) " -"的Cairo版本\n" +"这是 [Solidity by example Vault](https://solidity-by-example.org/defi/" +"vault/) 的Cairo版本\n" "以下是它的工作原理:" #: src/ch01/simple_vault.md:6 msgid "" -"- When a user deposits a token, the contract calculates the amount of shares " -"to mint.\n" -"\n" -"- When a user withdraws, the contract burns their shares, calculates the " +"When a user deposits a token, the contract calculates the amount of shares " +"to mint." +msgstr "" + +#: src/ch01/simple_vault.md:8 +#, fuzzy +msgid "" +"When a user withdraws, the contract burns their shares, calculates the " "yield, and withdraw both the yield and the initial amount of token deposited." msgstr "" "- 当用户存入代笔时,合约会计算要铸造的份额数量。\n" @@ -4272,188 +2127,16 @@ msgstr "" "- 当用户取款时,合约会销毁他们的份额,计算收益,并提取存款的收益和初始代币金" "额。" -#: src/ch01/simple_vault.md:10 +#: src/ch01/simple_vault.md:12 msgid "" -"```rust\n" -"use starknet::{ContractAddress};\n" -"\n" "// In order to make contract calls within our Vault,\n" "// we need to have the interface of the remote ERC20 contract defined to " "import the Dispatcher.\n" -"#[starknet::interface]\n" -"trait IERC20 {\n" -" fn name(self: @TContractState) -> felt252;\n" -" fn symbol(self: @TContractState) -> felt252;\n" -" fn decimals(self: @TContractState) -> u8;\n" -" fn total_supply(self: @TContractState) -> u256;\n" -" fn balance_of(self: @TContractState, account: ContractAddress) -> u256;\n" -" fn allowance(self: @TContractState, owner: ContractAddress, spender: " -"ContractAddress) -> u256;\n" -" fn transfer(ref self: TContractState, recipient: ContractAddress, amount: " -"u256) -> bool;\n" -" fn transfer_from(\n" -" ref self: TContractState, sender: ContractAddress, recipient: " -"ContractAddress, amount: u256\n" -" ) -> bool;\n" -" fn approve(ref self: TContractState, spender: ContractAddress, amount: " -"u256) -> bool;\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ISimpleVault {\n" -" fn deposit(ref self: TContractState, amount: u256);\n" -" fn withdraw(ref self: TContractState, shares: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleVault {\n" -" use super::{IERC20Dispatcher, IERC20DispatcherTrait};\n" -" use starknet::{ContractAddress, get_caller_address, " -"get_contract_address};\n" -" #[storage]\n" -" struct Storage {\n" -" token: IERC20Dispatcher,\n" -" total_supply: u256,\n" -" balance_of: LegacyMap\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, token: ContractAddress) {\n" -" self.token.write(IERC20Dispatcher { contract_address: token });\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" fn _mint(ref self: ContractState, to: ContractAddress, shares: u256) " -"{\n" -" self.total_supply.write(self.total_supply.read() + shares);\n" -" self.balance_of.write(to, self.balance_of.read(to) + shares);\n" -" }\n" -"\n" -" fn _burn(ref self: ContractState, from: ContractAddress, shares: " -"u256) {\n" -" self.total_supply.write(self.total_supply.read() - shares);\n" -" self.balance_of.write(from, self.balance_of.read(from) - " -"shares);\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleVault of super::ISimpleVault {\n" -" fn deposit(ref self: ContractState, amount: u256) {\n" -" // a = amount\n" -" // B = balance of token before deposit\n" -" // T = total supply\n" -" // s = shares to mint\n" -" //\n" -" // (T + s) / T = (a + B) / B \n" -" //\n" -" // s = aT / B\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -"\n" -" let mut shares = 0;\n" -" if self.total_supply.read() == 0 {\n" -" shares = amount;\n" -" } else {\n" -" let balance = self.token.read().balance_of(this);\n" -" shares = (amount * self.total_supply.read()) / balance;\n" -" }\n" -"\n" -" PrivateFunctions::_mint(ref self, caller, shares);\n" -" self.token.read().transfer_from(caller, this, amount);\n" -" }\n" -"\n" -" fn withdraw(ref self: ContractState, shares: u256) {\n" -" // a = amount\n" -" // B = balance of token before withdraw\n" -" // T = total supply\n" -" // s = shares to burn\n" -" //\n" -" // (T - s) / T = (B - a) / B \n" -" //\n" -" // a = sB / T\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -"\n" -" let balance = self.token.read().balance_of(this);\n" -" let amount = (shares * balance) / self.total_supply.read();\n" -" PrivateFunctions::_burn(ref self, caller, shares);\n" -" self.token.read().transfer(caller, amount);\n" -" }\n" -" }\n" -"}\n" -"\n" -"```" msgstr "" -"```rust\n" -"use starknet::{ContractAddress};\n" -"\n" -"// In order to make contract calls within our Vault,\n" -"// we need to have the interface of the remote ERC20 contract defined to " -"import the Dispatcher.\n" -"#[starknet::interface]\n" -"trait IERC20 {\n" -" fn name(self: @TContractState) -> felt252;\n" -" fn symbol(self: @TContractState) -> felt252;\n" -" fn decimals(self: @TContractState) -> u8;\n" -" fn total_supply(self: @TContractState) -> u256;\n" -" fn balance_of(self: @TContractState, account: ContractAddress) -> u256;\n" -" fn allowance(self: @TContractState, owner: ContractAddress, spender: " -"ContractAddress) -> u256;\n" -" fn transfer(ref self: TContractState, recipient: ContractAddress, amount: " -"u256) -> bool;\n" -" fn transfer_from(\n" -" ref self: TContractState, sender: ContractAddress, recipient: " -"ContractAddress, amount: u256\n" -" ) -> bool;\n" -" fn approve(ref self: TContractState, spender: ContractAddress, amount: " -"u256) -> bool;\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait ISimpleVault {\n" -" fn deposit(ref self: TContractState, amount: u256);\n" -" fn withdraw(ref self: TContractState, shares: u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod SimpleVault {\n" -" use super::{IERC20Dispatcher, IERC20DispatcherTrait};\n" -" use starknet::{ContractAddress, get_caller_address, " -"get_contract_address};\n" -" #[storage]\n" -" struct Storage {\n" -" token: IERC20Dispatcher,\n" -" total_supply: u256,\n" -" balance_of: LegacyMap\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(ref self: ContractState, token: ContractAddress) {\n" -" self.token.write(IERC20Dispatcher { contract_address: token });\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" fn _mint(ref self: ContractState, to: ContractAddress, shares: u256) " -"{\n" -" self.total_supply.write(self.total_supply.read() + shares);\n" -" self.balance_of.write(to, self.balance_of.read(to) + shares);\n" -" }\n" -"\n" -" fn _burn(ref self: ContractState, from: ContractAddress, shares: " -"u256) {\n" -" self.total_supply.write(self.total_supply.read() - shares);\n" -" self.balance_of.write(from, self.balance_of.read(from) - " -"shares);\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SimpleVault of super::ISimpleVault {\n" -" fn deposit(ref self: ContractState, amount: u256) {\n" -" // a = amount\n" + +#: src/ch01/simple_vault.md:68 +msgid "" +"// a = amount\n" " // B = balance of token before deposit\n" " // T = total supply\n" " // s = shares to mint\n" @@ -4461,23 +2144,11 @@ msgstr "" " // (T + s) / T = (a + B) / B \n" " //\n" " // s = aT / B\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -"\n" -" let mut shares = 0;\n" -" if self.total_supply.read() == 0 {\n" -" shares = amount;\n" -" } else {\n" -" let balance = self.token.read().balance_of(this);\n" -" shares = (amount * self.total_supply.read()) / balance;\n" -" }\n" -"\n" -" PrivateFunctions::_mint(ref self, caller, shares);\n" -" self.token.read().transfer_from(caller, this, amount);\n" -" }\n" -"\n" -" fn withdraw(ref self: ContractState, shares: u256) {\n" -" // a = amount\n" +msgstr "" + +#: src/ch01/simple_vault.md:92 +msgid "" +"// a = amount\n" " // B = balance of token before withdraw\n" " // T = total supply\n" " // s = shares to burn\n" @@ -4485,18 +2156,7 @@ msgstr "" " // (T - s) / T = (B - a) / B \n" " //\n" " // a = sB / T\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -"\n" -" let balance = self.token.read().balance_of(this);\n" -" let amount = (shares * balance) / self.total_supply.read();\n" -" PrivateFunctions::_burn(ref self, caller, shares);\n" -" self.token.read().transfer(caller, amount);\n" -" }\n" -" }\n" -"}\n" -"\n" -"```" +msgstr "" #: src/ch01/simple_vault.md:113 msgid "" @@ -4508,10 +2168,6 @@ msgstr "" "com/NethermindEth/StarknetByExample/blob/main/listings/ch01-applications/" "simple_vault/src/simple_vault.cairo) 中尝试这个合约。" -#: src/ch01/erc20.md:1 -msgid "# ERC20 Token" -msgstr "# ERC20 代币" - #: src/ch01/erc20.md:3 msgid "" "Contracts that follow the [ERC20 Standard](https://eips.ethereum.org/EIPS/" @@ -4521,493 +2177,29 @@ msgstr "" "ERC20 代币。它们用于代表可互换的资产。" #: src/ch01/erc20.md:5 -msgid "To create an ERC20 conctract, it must implement the following interface:" -msgstr "要创建 ERC20 合约,必须实现以下接口:" - -#: src/ch01/erc20.md:7 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IERC20 {\n" -" fn get_name(self: @TContractState) -> felt252;\n" -" fn get_symbol(self: @TContractState) -> felt252;\n" -" fn get_decimals(self: @TContractState) -> u8;\n" -" fn get_total_supply(self: @TContractState) -> felt252;\n" -" fn balance_of(self: @TContractState, account: ContractAddress) -> " -"felt252;\n" -" fn allowance(\n" -" self: @TContractState, owner: ContractAddress, spender: " -"ContractAddress\n" -" ) -> felt252;\n" -" fn transfer(ref self: TContractState, recipient: ContractAddress, amount: " -"felt252);\n" -" fn transfer_from(\n" -" ref self: TContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" );\n" -" fn approve(ref self: TContractState, spender: ContractAddress, amount: " -"felt252);\n" -" fn increase_allowance(ref self: TContractState, spender: ContractAddress, " -"added_value: felt252);\n" -" fn decrease_allowance(\n" -" ref self: TContractState, spender: ContractAddress, subtracted_value: " -"felt252\n" -" );\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IERC20 {\n" -" fn get_name(self: @TContractState) -> felt252;\n" -" fn get_symbol(self: @TContractState) -> felt252;\n" -" fn get_decimals(self: @TContractState) -> u8;\n" -" fn get_total_supply(self: @TContractState) -> felt252;\n" -" fn balance_of(self: @TContractState, account: ContractAddress) -> " -"felt252;\n" -" fn allowance(\n" -" self: @TContractState, owner: ContractAddress, spender: " -"ContractAddress\n" -" ) -> felt252;\n" -" fn transfer(ref self: TContractState, recipient: ContractAddress, amount: " -"felt252);\n" -" fn transfer_from(\n" -" ref self: TContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" );\n" -" fn approve(ref self: TContractState, spender: ContractAddress, amount: " -"felt252);\n" -" fn increase_allowance(ref self: TContractState, spender: ContractAddress, " -"added_value: felt252);\n" -" fn decrease_allowance(\n" -" ref self: TContractState, spender: ContractAddress, subtracted_value: " -"felt252\n" -" );\n" -"}\n" -"```" +"To create an ERC20 conctract, it must implement the following interface:" +msgstr "要创建 ERC20 合约,必须实现以下接口:" #: src/ch01/erc20.md:33 +#, fuzzy msgid "" -"In Starknet, function names should be written in *snake_case*. This is not " -"the case in Solidity, where function names are written in *camelCase*.\n" -"The Starknet ERC20 interface is therefore slightly different from the " -"Solidity ERC20 interface." +"In Starknet, function names should be written in _snake_case_. This is not " +"the case in Solidity, where function names are written in _camelCase_. The " +"Starknet ERC20 interface is therefore slightly different from the Solidity " +"ERC20 interface." msgstr "" -"在Starknet中,函数名应该使用*snake_case*(蛇形命名法)。而在Solidity中,函数名" -"使用*camelCase*(驼峰命名法)。因此,Starknet的ERC20接口与Solidity的ERC20接口" -"略有不同。" +"在Starknet中,函数名应该使用*snake_case*(蛇形命名法)。而在Solidity中,函数" +"名使用*camelCase*(驼峰命名法)。因此,Starknet的ERC20接口与Solidity的ERC20接" +"口略有不同。" #: src/ch01/erc20.md:36 msgid "Here's an implementation of the ERC20 interface in Cairo:" msgstr "以下是一个在Cairo中实现的ERC20接口的示例:" -#: src/ch01/erc20.md:38 -msgid "" -"```rust\n" -"#[starknet::contract]\n" -"mod erc20 {\n" -" use zeroable::Zeroable;\n" -" use starknet::get_caller_address;\n" -" use starknet::contract_address_const;\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" name: felt252,\n" -" symbol: felt252,\n" -" decimals: u8,\n" -" total_supply: felt252,\n" -" balances: LegacyMap::,\n" -" allowances: LegacyMap::<(ContractAddress, ContractAddress), " -"felt252>,\n" -" }\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Transfer: Transfer,\n" -" Approval: Approval,\n" -" }\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Transfer {\n" -" from: ContractAddress,\n" -" to: ContractAddress,\n" -" value: felt252,\n" -" }\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Approval {\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" value: felt252,\n" -" }\n" -"\n" -" mod Errors {\n" -" const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0';\n" -" const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0';\n" -" const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0';\n" -" const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0';\n" -" const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0';\n" -" const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0';\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(\n" -" ref self: ContractState,\n" -" recipient: ContractAddress,\n" -" name: felt252,\n" -" decimals: u8,\n" -" initial_supply: felt252,\n" -" symbol: felt252\n" -" ) {\n" -" self.name.write(name);\n" -" self.symbol.write(symbol);\n" -" self.decimals.write(decimals);\n" -" self.mint(recipient, initial_supply);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl IERC20Impl of super::IERC20 {\n" -" fn get_name(self: @ContractState) -> felt252 {\n" -" self.name.read()\n" -" }\n" -"\n" -" fn get_symbol(self: @ContractState) -> felt252 {\n" -" self.symbol.read()\n" -" }\n" -"\n" -" fn get_decimals(self: @ContractState) -> u8 {\n" -" self.decimals.read()\n" -" }\n" -"\n" -" fn get_total_supply(self: @ContractState) -> felt252 {\n" -" self.total_supply.read()\n" -" }\n" -"\n" -" fn balance_of(self: @ContractState, account: ContractAddress) -> " -"felt252 {\n" -" self.balances.read(account)\n" -" }\n" -"\n" -" fn allowance(\n" -" self: @ContractState, owner: ContractAddress, spender: " -"ContractAddress\n" -" ) -> felt252 {\n" -" self.allowances.read((owner, spender))\n" -" }\n" -"\n" -" fn transfer(ref self: ContractState, recipient: ContractAddress, " -"amount: felt252) {\n" -" let sender = get_caller_address();\n" -" self._transfer(sender, recipient, amount);\n" -" }\n" -"\n" -" fn transfer_from(\n" -" ref self: ContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self.spend_allowance(sender, caller, amount);\n" -" self._transfer(sender, recipient, amount);\n" -" }\n" -"\n" -" fn approve(ref self: ContractState, spender: ContractAddress, amount: " -"felt252) {\n" -" let caller = get_caller_address();\n" -" self.approve_helper(caller, spender, amount);\n" -" }\n" -"\n" -" fn increase_allowance(\n" -" ref self: ContractState, spender: ContractAddress, added_value: " -"felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self\n" -" .approve_helper(\n" -" caller, spender, self.allowances.read((caller, spender)) " -"+ added_value\n" -" );\n" -" }\n" -"\n" -" fn decrease_allowance(\n" -" ref self: ContractState, spender: ContractAddress, " -"subtracted_value: felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self\n" -" .approve_helper(\n" -" caller, spender, self.allowances.read((caller, spender)) " -"- subtracted_value\n" -" );\n" -" }\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl InternalImpl of InternalTrait {\n" -" fn _transfer(\n" -" ref self: ContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" assert(!sender.is_zero(), Errors::TRANSFER_FROM_ZERO);\n" -" assert(!recipient.is_zero(), Errors::TRANSFER_TO_ZERO);\n" -" self.balances.write(sender, self.balances.read(sender) - " -"amount);\n" -" self.balances.write(recipient, self.balances.read(recipient) + " -"amount);\n" -" self.emit(Transfer { from: sender, to: recipient, value: " -"amount });\n" -" }\n" -"\n" -" fn spend_allowance(\n" -" ref self: ContractState,\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" let allowance = self.allowances.read((owner, spender));\n" -" self.allowances.write((owner, spender), allowance - amount);\n" -" }\n" -"\n" -" fn approve_helper(\n" -" ref self: ContractState,\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" assert(!spender.is_zero(), Errors::APPROVE_TO_ZERO);\n" -" self.allowances.write((owner, spender), amount);\n" -" self.emit(Approval { owner, spender, value: amount });\n" -" }\n" -"\n" -" fn mint(ref self: ContractState, recipient: ContractAddress, amount: " -"felt252) {\n" -" assert(!recipient.is_zero(), Errors::MINT_TO_ZERO);\n" -" let supply = self.total_supply.read() + amount; // What can go " -"wrong here?\n" -" self.total_supply.write(supply);\n" -" let balance = self.balances.read(recipient) + amount;\n" -" self.balances.write(recipient, amount);\n" -" self\n" -" .emit(\n" -" Event::Transfer(\n" -" Transfer {\n" -" from: contract_address_const::<0>(), to: " -"recipient, value: amount\n" -" }\n" -" )\n" -" );\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/ch01/erc20.md:207 +msgid "// What can go wrong here?\n" msgstr "" -"```rust\n" -"#[starknet::contract]\n" -"mod erc20 {\n" -" use zeroable::Zeroable;\n" -" use starknet::get_caller_address;\n" -" use starknet::contract_address_const;\n" -" use starknet::ContractAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" name: felt252,\n" -" symbol: felt252,\n" -" decimals: u8,\n" -" total_supply: felt252,\n" -" balances: LegacyMap::,\n" -" allowances: LegacyMap::<(ContractAddress, ContractAddress), " -"felt252>,\n" -" }\n" -"\n" -" #[event]\n" -" #[derive(Drop, starknet::Event)]\n" -" enum Event {\n" -" Transfer: Transfer,\n" -" Approval: Approval,\n" -" }\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Transfer {\n" -" from: ContractAddress,\n" -" to: ContractAddress,\n" -" value: felt252,\n" -" }\n" -" #[derive(Drop, starknet::Event)]\n" -" struct Approval {\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" value: felt252,\n" -" }\n" -"\n" -" mod Errors {\n" -" const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0';\n" -" const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0';\n" -" const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0';\n" -" const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0';\n" -" const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0';\n" -" const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0';\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(\n" -" ref self: ContractState,\n" -" recipient: ContractAddress,\n" -" name: felt252,\n" -" decimals: u8,\n" -" initial_supply: felt252,\n" -" symbol: felt252\n" -" ) {\n" -" self.name.write(name);\n" -" self.symbol.write(symbol);\n" -" self.decimals.write(decimals);\n" -" self.mint(recipient, initial_supply);\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl IERC20Impl of super::IERC20 {\n" -" fn get_name(self: @ContractState) -> felt252 {\n" -" self.name.read()\n" -" }\n" -"\n" -" fn get_symbol(self: @ContractState) -> felt252 {\n" -" self.symbol.read()\n" -" }\n" -"\n" -" fn get_decimals(self: @ContractState) -> u8 {\n" -" self.decimals.read()\n" -" }\n" -"\n" -" fn get_total_supply(self: @ContractState) -> felt252 {\n" -" self.total_supply.read()\n" -" }\n" -"\n" -" fn balance_of(self: @ContractState, account: ContractAddress) -> " -"felt252 {\n" -" self.balances.read(account)\n" -" }\n" -"\n" -" fn allowance(\n" -" self: @ContractState, owner: ContractAddress, spender: " -"ContractAddress\n" -" ) -> felt252 {\n" -" self.allowances.read((owner, spender))\n" -" }\n" -"\n" -" fn transfer(ref self: ContractState, recipient: ContractAddress, " -"amount: felt252) {\n" -" let sender = get_caller_address();\n" -" self._transfer(sender, recipient, amount);\n" -" }\n" -"\n" -" fn transfer_from(\n" -" ref self: ContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self.spend_allowance(sender, caller, amount);\n" -" self._transfer(sender, recipient, amount);\n" -" }\n" -"\n" -" fn approve(ref self: ContractState, spender: ContractAddress, amount: " -"felt252) {\n" -" let caller = get_caller_address();\n" -" self.approve_helper(caller, spender, amount);\n" -" }\n" -"\n" -" fn increase_allowance(\n" -" ref self: ContractState, spender: ContractAddress, added_value: " -"felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self\n" -" .approve_helper(\n" -" caller, spender, self.allowances.read((caller, spender)) " -"+ added_value\n" -" );\n" -" }\n" -"\n" -" fn decrease_allowance(\n" -" ref self: ContractState, spender: ContractAddress, " -"subtracted_value: felt252\n" -" ) {\n" -" let caller = get_caller_address();\n" -" self\n" -" .approve_helper(\n" -" caller, spender, self.allowances.read((caller, spender)) " -"- subtracted_value\n" -" );\n" -" }\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl InternalImpl of InternalTrait {\n" -" fn _transfer(\n" -" ref self: ContractState,\n" -" sender: ContractAddress,\n" -" recipient: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" assert(!sender.is_zero(), Errors::TRANSFER_FROM_ZERO);\n" -" assert(!recipient.is_zero(), Errors::TRANSFER_TO_ZERO);\n" -" self.balances.write(sender, self.balances.read(sender) - " -"amount);\n" -" self.balances.write(recipient, self.balances.read(recipient) + " -"amount);\n" -" self.emit(Transfer { from: sender, to: recipient, value: " -"amount });\n" -" }\n" -"\n" -" fn spend_allowance(\n" -" ref self: ContractState,\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" let allowance = self.allowances.read((owner, spender));\n" -" self.allowances.write((owner, spender), allowance - amount);\n" -" }\n" -"\n" -" fn approve_helper(\n" -" ref self: ContractState,\n" -" owner: ContractAddress,\n" -" spender: ContractAddress,\n" -" amount: felt252\n" -" ) {\n" -" assert(!spender.is_zero(), Errors::APPROVE_TO_ZERO);\n" -" self.allowances.write((owner, spender), amount);\n" -" self.emit(Approval { owner, spender, value: amount });\n" -" }\n" -"\n" -" fn mint(ref self: ContractState, recipient: ContractAddress, amount: " -"felt252) {\n" -" assert(!recipient.is_zero(), Errors::MINT_TO_ZERO);\n" -" let supply = self.total_supply.read() + amount; // What can go " -"wrong here?\n" -" self.total_supply.write(supply);\n" -" let balance = self.balances.read(recipient) + amount;\n" -" self.balances.write(recipient, amount);\n" -" self\n" -" .emit(\n" -" Event::Transfer(\n" -" Transfer {\n" -" from: contract_address_const::<0>(), to: " -"recipient, value: amount\n" -" }\n" -" )\n" -" );\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch01/erc20.md:224 msgid "" @@ -5026,442 +2218,30 @@ msgid "" "(https://cairo-by-example.com/examples/erc20/) ones." msgstr "" "还有一些其他的实现,比如 [Open Zeppelin](https://docs.openzeppelin.com/" -"contracts-cairo/0.7.0/erc20) 或者 [Cairo By Example](https://cairo-by-example." -"com/examples/erc20/) 中的实现。" - -#: src/ch01/erc20.md:228 -msgid "
Last change: 2023-10-24
" -msgstr "
Last change: 2023-10-24
" - -#: src/ch01/constant-product-amm.md:1 -msgid "# Constant Product AMM" -msgstr "# 恒定乘积自动做市商" +"contracts-cairo/0.7.0/erc20) 或者 [Cairo By Example](https://cairo-by-" +"example.com/examples/erc20/) 中的实现。" #: src/ch01/constant-product-amm.md:3 msgid "" -"This is the Cairo adaptation of the [Solidity by example Constant Product AMM]" -"(https://solidity-by-example.org/defi/constant-product-amm/)." +"This is the Cairo adaptation of the [Solidity by example Constant Product " +"AMM](https://solidity-by-example.org/defi/constant-product-amm/)." msgstr "" "这个是 用Cairo 改编的 [Solidity by example Constant Product AMM](https://" "solidity-by-example.org/defi/constant-product-amm/)." -#: src/ch01/constant-product-amm.md:5 +#: src/ch01/constant-product-amm.md:32 msgid "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IConstantProductAmm {\n" -" fn swap(ref self: TContractState, token_in: ContractAddress, amount_in: " -"u256) -> u256;\n" -" fn add_liquidity(ref self: TContractState, amount0: u256, amount1: u256) -" -"> u256;\n" -" fn remove_liquidity(ref self: TContractState, shares: u256) -> (u256, " -"u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ConstantProductAmm {\n" -" use core::traits::Into;\n" -" use openzeppelin::token::erc20::interface::{IERC20Dispatcher, " -"IERC20DispatcherTrait};\n" -" use starknet::{\n" -" ContractAddress, get_caller_address, get_contract_address, " -"contract_address_const\n" -" };\n" -" use integer::u256_sqrt;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" token0: IERC20Dispatcher,\n" -" token1: IERC20Dispatcher,\n" -" reserve0: u256,\n" -" reserve1: u256,\n" -" total_supply: u256,\n" -" balance_of: LegacyMap::,\n" -" // Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" +"// Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" " // E.g. 3 = 0.3%\n" -" fee: u16,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(\n" -" ref self: ContractState, token0: ContractAddress, token1: " -"ContractAddress, fee: u16\n" -" ) {\n" -" // assert(fee <= 1000, 'fee > 1000');\n" -" self.token0.write(IERC20Dispatcher { contract_address: token0 });\n" -" self.token1.write(IERC20Dispatcher { contract_address: token1 });\n" -" self.fee.write(fee);\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" fn _mint(ref self: ContractState, to: ContractAddress, amount: u256) " -"{\n" -" self.balance_of.write(to, self.balance_of.read(to) + amount);\n" -" self.total_supply.write(self.total_supply.read() + amount);\n" -" }\n" -"\n" -" fn _burn(ref self: ContractState, from: ContractAddress, amount: " -"u256) {\n" -" self.balance_of.write(from, self.balance_of.read(from) - " -"amount);\n" -" self.total_supply.write(self.total_supply.read() - amount);\n" -" }\n" -"\n" -" fn _update(ref self: ContractState, reserve0: u256, reserve1: u256) " -"{\n" -" self.reserve0.write(reserve0);\n" -" self.reserve1.write(reserve1);\n" -" }\n" -"\n" -" #[inline(always)]\n" -" fn select_token(self: @ContractState, token: ContractAddress) -> bool " -"{\n" -" assert(\n" -" token == self.token0.read().contract_address\n" -" || token == self.token1.read().contract_address,\n" -" 'invalid token'\n" -" );\n" -" token == self.token0.read().contract_address\n" -" }\n" -"\n" -" #[inline(always)]\n" -" fn min(x: u256, y: u256) -> u256 {\n" -" if (x <= y) {\n" -" x\n" -" } else {\n" -" y\n" -" }\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ConstantProductAmm of super::IConstantProductAmm {\n" -" fn swap(ref self: ContractState, token_in: ContractAddress, " -"amount_in: u256) -> u256 {\n" -" assert(amount_in > 0, 'amount in = 0');\n" -" let is_token0: bool = self.select_token(token_in);\n" -"\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -" let (reserve0, reserve1): (u256, u256) = (self.reserve0.read(), " -"self.reserve1.read());\n" -" let (\n" -" token_in, token_out, reserve_in, reserve_out\n" -" ): (IERC20Dispatcher, IERC20Dispatcher, u256, u256) =\n" -" if (is_token0) {\n" -" (token0, token1, reserve0, reserve1)\n" -" } else {\n" -" (token1, token0, reserve1, reserve0)\n" -" };\n" -"\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" token_in.transfer_from(caller, this, amount_in);\n" -"\n" -" // How much dy for dx?\n" -" // xy = k\n" -" // (x + dx)(y - dy) = k\n" -" // y - dy = k / (x + dx)\n" -" // y - k / (x + dx) = dy\n" -" // y - xy / (x + dx) = dy\n" -" // (yx + ydx - xy) / (x + dx) = dy\n" -" // ydx / (x + dx) = dy\n" -"\n" -" let amount_in_with_fee = (amount_in * (1000 - self.fee.read()." -"into()) / 1000);\n" -" let amount_out = (reserve_out * amount_in_with_fee) / (reserve_in " -"+ amount_in_with_fee);\n" -"\n" -" token_out.transfer(caller, amount_out);\n" -"\n" -" self._update(self.token0.read().balance_of(this), self.token1." -"read().balance_of(this));\n" -" amount_out\n" -" }\n" -"\n" -" fn add_liquidity(ref self: ContractState, amount0: u256, amount1: " -"u256) -> u256 {\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -"\n" -" token0.transfer_from(caller, this, amount0);\n" -" token1.transfer_from(caller, this, amount1);\n" -"\n" -" // How much dx, dy to add?\n" -" //\n" -" // xy = k\n" -" // (x + dx)(y + dy) = k'\n" -" //\n" -" // No price change, before and after adding liquidity\n" -" // x / y = (x + dx) / (y + dy)\n" -" //\n" -" // x(y + dy) = y(x + dx)\n" -" // x * dy = y * dx\n" -" //\n" -" // x / y = dx / dy\n" -" // dy = y / x * dx\n" -"\n" -" let (reserve0, reserve1): (u256, u256) = (self.reserve0.read(), " -"self.reserve1.read());\n" -" if (reserve0 > 0 || reserve1 > 0) {\n" -" assert(reserve0 * amount1 == reserve1 * amount0, 'x / y != " -"dx / dy');\n" -" }\n" -"\n" -" // How much shares to mint?\n" -" //\n" -" // f(x, y) = value of liquidity\n" -" // We will define f(x, y) = sqrt(xy)\n" -" //\n" -" // L0 = f(x, y)\n" -" // L1 = f(x + dx, y + dy)\n" -" // T = total shares\n" -" // s = shares to mint\n" -" //\n" -" // Total shares should increase proportional to increase in " -"liquidity\n" -" // L1 / L0 = (T + s) / T\n" -" //\n" -" // L1 * T = L0 * (T + s)\n" -" //\n" -" // (L1 - L0) * T / L0 = s\n" -"\n" -" // Claim\n" -" // (L1 - L0) / L0 = dx / x = dy / y\n" -" //\n" -" // Proof\n" -" // --- Equation 1 ---\n" -" // (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / " -"sqrt(xy)\n" -" //\n" -" // dx / dy = x / y so replace dy = dx * y / x\n" -" //\n" -" // --- Equation 2 ---\n" -" // Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / " -"sqrt(xy)\n" -" //\n" -" // Multiply by sqrt(x) / sqrt(x)\n" -" // Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - sqrt(x^2y)) / " -"sqrt(x^2y)\n" -" // = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " -"(sqrt(y)sqrt(x^2))\n" -" // sqrt(y) on top and bottom cancels out\n" -" //\n" -" // --- Equation 3 ---\n" -" // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " -"(sqrt(x^2)\n" -" // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)\n" -" // = ((x + dx) - x) / x\n" -" // = dx / x\n" -" // Since dx / dy = x / y,\n" -" // dx / x = dy / y\n" -" //\n" -" // Finally\n" -" // (L1 - L0) / L0 = dx / x = dy / y\n" -"\n" -" let total_supply = self.total_supply.read();\n" -" let shares = if (total_supply == 0) {\n" -" u256_sqrt(amount0 * amount1).into()\n" -" } else {\n" -" PrivateFunctions::min(\n" -" amount0 * total_supply / reserve0, amount1 * " -"total_supply / reserve1\n" -" )\n" -" };\n" -" assert(shares > 0, 'shares = 0');\n" -" self._mint(caller, shares);\n" -"\n" -" self._update(self.token0.read().balance_of(this), self.token1." -"read().balance_of(this));\n" -" shares\n" -" }\n" -"\n" -" fn remove_liquidity(ref self: ContractState, shares: u256) -> (u256, " -"u256) {\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -"\n" -" // Claim\n" -" // dx, dy = amount of liquidity to remove\n" -" // dx = s / T * x\n" -" // dy = s / T * y\n" -" //\n" -" // Proof\n" -" // Let's find dx, dy such that\n" -" // v / L = s / T\n" -" //\n" -" // where\n" -" // v = f(dx, dy) = sqrt(dxdy)\n" -" // L = total liquidity = sqrt(xy)\n" -" // s = shares\n" -" // T = total supply\n" -" //\n" -" // --- Equation 1 ---\n" -" // v = s / T * L\n" -" // sqrt(dxdy) = s / T * sqrt(xy)\n" -" //\n" -" // Amount of liquidity to remove must not change price so\n" -" // dx / dy = x / y\n" -" //\n" -" // replace dy = dx * y / x\n" -" // sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)\n" -" //\n" -" // Divide both sides of Equation 1 with sqrt(y / x)\n" -" // dx = s / T * sqrt(xy) / sqrt(y / x)\n" -" // = s / T * sqrt(x^2) = s / T * x\n" -" //\n" -" // Likewise\n" -" // dy = s / T * y\n" -"\n" -" // bal0 >= reserve0\n" -" // bal1 >= reserve1\n" -" let (bal0, bal1): (u256, u256) = (token0.balance_of(this), token1." -"balance_of(this));\n" -"\n" -" let total_supply = self.total_supply.read();\n" -" let (amount0, amount1): (u256, u256) = (\n" -" (shares * bal0) / total_supply, (shares * bal1) / " -"total_supply\n" -" );\n" -" assert(amount0 > 0 && amount1 > 0, 'amount0 or amount1 = 0');\n" -"\n" -" self._burn(caller, shares);\n" -" self._update(bal0 - amount0, bal1 - amount1);\n" -"\n" -" token0.transfer(caller, amount0);\n" -" token1.transfer(caller, amount1);\n" -" (amount0, amount1)\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"use starknet::ContractAddress;\n" -"\n" -"#[starknet::interface]\n" -"trait IConstantProductAmm {\n" -" fn swap(ref self: TContractState, token_in: ContractAddress, amount_in: " -"u256) -> u256;\n" -" fn add_liquidity(ref self: TContractState, amount0: u256, amount1: u256) -" -"> u256;\n" -" fn remove_liquidity(ref self: TContractState, shares: u256) -> (u256, " -"u256);\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ConstantProductAmm {\n" -" use core::traits::Into;\n" -" use openzeppelin::token::erc20::interface::{IERC20Dispatcher, " -"IERC20DispatcherTrait};\n" -" use starknet::{\n" -" ContractAddress, get_caller_address, get_contract_address, " -"contract_address_const\n" -" };\n" -" use integer::u256_sqrt;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" token0: IERC20Dispatcher,\n" -" token1: IERC20Dispatcher,\n" -" reserve0: u256,\n" -" reserve1: u256,\n" -" total_supply: u256,\n" -" balance_of: LegacyMap::,\n" -" // Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" -" // E.g. 3 = 0.3%\n" -" fee: u16,\n" -" }\n" -"\n" -" #[constructor]\n" -" fn constructor(\n" -" ref self: ContractState, token0: ContractAddress, token1: " -"ContractAddress, fee: u16\n" -" ) {\n" -" // assert(fee <= 1000, 'fee > 1000');\n" -" self.token0.write(IERC20Dispatcher { contract_address: token0 });\n" -" self.token1.write(IERC20Dispatcher { contract_address: token1 });\n" -" self.fee.write(fee);\n" -" }\n" -"\n" -" #[generate_trait]\n" -" impl PrivateFunctions of PrivateFunctionsTrait {\n" -" fn _mint(ref self: ContractState, to: ContractAddress, amount: u256) " -"{\n" -" self.balance_of.write(to, self.balance_of.read(to) + amount);\n" -" self.total_supply.write(self.total_supply.read() + amount);\n" -" }\n" -"\n" -" fn _burn(ref self: ContractState, from: ContractAddress, amount: " -"u256) {\n" -" self.balance_of.write(from, self.balance_of.read(from) - " -"amount);\n" -" self.total_supply.write(self.total_supply.read() - amount);\n" -" }\n" -"\n" -" fn _update(ref self: ContractState, reserve0: u256, reserve1: u256) " -"{\n" -" self.reserve0.write(reserve0);\n" -" self.reserve1.write(reserve1);\n" -" }\n" -"\n" -" #[inline(always)]\n" -" fn select_token(self: @ContractState, token: ContractAddress) -> bool " -"{\n" -" assert(\n" -" token == self.token0.read().contract_address\n" -" || token == self.token1.read().contract_address,\n" -" 'invalid token'\n" -" );\n" -" token == self.token0.read().contract_address\n" -" }\n" -"\n" -" #[inline(always)]\n" -" fn min(x: u256, y: u256) -> u256 {\n" -" if (x <= y) {\n" -" x\n" -" } else {\n" -" y\n" -" }\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ConstantProductAmm of super::IConstantProductAmm {\n" -" fn swap(ref self: ContractState, token_in: ContractAddress, " -"amount_in: u256) -> u256 {\n" -" assert(amount_in > 0, 'amount in = 0');\n" -" let is_token0: bool = self.select_token(token_in);\n" -"\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -" let (reserve0, reserve1): (u256, u256) = (self.reserve0.read(), " -"self.reserve1.read());\n" -" let (\n" -" token_in, token_out, reserve_in, reserve_out\n" -" ): (IERC20Dispatcher, IERC20Dispatcher, u256, u256) =\n" -" if (is_token0) {\n" -" (token0, token1, reserve0, reserve1)\n" -" } else {\n" -" (token1, token0, reserve1, reserve0)\n" -" };\n" -"\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" token_in.transfer_from(caller, this, amount_in);\n" -"\n" -" // How much dy for dx?\n" + +#: src/ch01/constant-product-amm.md:41 +msgid "// assert(fee <= 1000, 'fee > 1000');\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:107 +msgid "" +"// How much dy for dx?\n" " // xy = k\n" " // (x + dx)(y - dy) = k\n" " // y - dy = k / (x + dx)\n" @@ -5469,31 +2249,11 @@ msgstr "" " // y - xy / (x + dx) = dy\n" " // (yx + ydx - xy) / (x + dx) = dy\n" " // ydx / (x + dx) = dy\n" -"\n" -" let amount_in_with_fee = (amount_in * (1000 - self.fee.read()." -"into()) / 1000);\n" -" let amount_out = (reserve_out * amount_in_with_fee) / (reserve_in " -"+ amount_in_with_fee);\n" -"\n" -" token_out.transfer(caller, amount_out);\n" -"\n" -" self._update(self.token0.read().balance_of(this), self.token1." -"read().balance_of(this));\n" -" amount_out\n" -" }\n" -"\n" -" fn add_liquidity(ref self: ContractState, amount0: u256, amount1: " -"u256) -> u256 {\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -"\n" -" token0.transfer_from(caller, this, amount0);\n" -" token1.transfer_from(caller, this, amount1);\n" -"\n" -" // How much dx, dy to add?\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:135 +msgid "" +"// How much dx, dy to add?\n" " //\n" " // xy = k\n" " // (x + dx)(y + dy) = k'\n" @@ -5506,15 +2266,11 @@ msgstr "" " //\n" " // x / y = dx / dy\n" " // dy = y / x * dx\n" -"\n" -" let (reserve0, reserve1): (u256, u256) = (self.reserve0.read(), " -"self.reserve1.read());\n" -" if (reserve0 > 0 || reserve1 > 0) {\n" -" assert(reserve0 * amount1 == reserve1 * amount0, 'x / y != " -"dx / dy');\n" -" }\n" -"\n" -" // How much shares to mint?\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:154 +msgid "" +"// How much shares to mint?\n" " //\n" " // f(x, y) = value of liquidity\n" " // We will define f(x, y) = sqrt(xy)\n" @@ -5531,8 +2287,11 @@ msgstr "" " // L1 * T = L0 * (T + s)\n" " //\n" " // (L1 - L0) * T / L0 = s\n" -"\n" -" // Claim\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:171 +msgid "" +"// Claim\n" " // (L1 - L0) / L0 = dx / x = dy / y\n" " //\n" " // Proof\n" @@ -5564,33 +2323,11 @@ msgstr "" " //\n" " // Finally\n" " // (L1 - L0) / L0 = dx / x = dy / y\n" -"\n" -" let total_supply = self.total_supply.read();\n" -" let shares = if (total_supply == 0) {\n" -" u256_sqrt(amount0 * amount1).into()\n" -" } else {\n" -" PrivateFunctions::min(\n" -" amount0 * total_supply / reserve0, amount1 * " -"total_supply / reserve1\n" -" )\n" -" };\n" -" assert(shares > 0, 'shares = 0');\n" -" self._mint(caller, shares);\n" -"\n" -" self._update(self.token0.read().balance_of(this), self.token1." -"read().balance_of(this));\n" -" shares\n" -" }\n" -"\n" -" fn remove_liquidity(ref self: ContractState, shares: u256) -> (u256, " -"u256) {\n" -" let caller = get_caller_address();\n" -" let this = get_contract_address();\n" -" let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = (\n" -" self.token0.read(), self.token1.read()\n" -" );\n" -"\n" -" // Claim\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:221 +msgid "" +"// Claim\n" " // dx, dy = amount of liquidity to remove\n" " // dx = s / T * x\n" " // dy = s / T * y\n" @@ -5621,29 +2358,13 @@ msgstr "" " //\n" " // Likewise\n" " // dy = s / T * y\n" -"\n" -" // bal0 >= reserve0\n" +msgstr "" + +#: src/ch01/constant-product-amm.md:253 +msgid "" +"// bal0 >= reserve0\n" " // bal1 >= reserve1\n" -" let (bal0, bal1): (u256, u256) = (token0.balance_of(this), token1." -"balance_of(this));\n" -"\n" -" let total_supply = self.total_supply.read();\n" -" let (amount0, amount1): (u256, u256) = (\n" -" (shares * bal0) / total_supply, (shares * bal1) / " -"total_supply\n" -" );\n" -" assert(amount0 > 0 && amount1 > 0, 'amount0 or amount1 = 0');\n" -"\n" -" self._burn(caller, shares);\n" -" self._update(bal0 - amount0, bal1 - amount1);\n" -"\n" -" token0.transfer(caller, amount0);\n" -" token1.transfer(caller, amount1);\n" -" (amount0, amount1)\n" -" }\n" -" }\n" -"}\n" -"```" +msgstr "" #: src/ch01/constant-product-amm.md:274 msgid "" @@ -5656,18 +2377,15 @@ msgstr "" "com/NethermindEth/StarknetByExample/blob/main/listings/ch01-applications/" "constant_product_amm/src/constant_product_amm.cairo) 中尝试这个合约。" -#: src/ch02/write_to_any_slot.md:1 -msgid "# Writing to any storage slot" -msgstr "# 写入任何存储槽" - #: src/ch02/write_to_any_slot.md:3 +#, fuzzy msgid "" "On Starknet, a contract's storage is a map with 2^251 slots, where each slot " -"is a felt which is initialized to 0.\n" -"The address of storage variables is computed at compile time using the " -"formula: `storage variable address := pedersen(keccak(variable name), keys)`. " -"Interactions with storage variables are commonly performed using the `self." -"var.read()` and `self.var.write()` functions." +"is a felt which is initialized to 0. The address of storage variables is " +"computed at compile time using the formula: `storage variable address := " +"pedersen(keccak(variable name), keys)`. Interactions with storage variables " +"are commonly performed using the `self.var.read()` and `self.var.write()` " +"functions." msgstr "" "在Starknet上,一个合约的存储是一个拥有 2^251 个槽的map,每个槽是一个初始化为 " "0 的 felt。存储变量的地址在编译时通过公式计算得出:`存储变量地址 := " @@ -5675,9 +2393,10 @@ msgstr "" "和 `self.var.write()` 。" #: src/ch02/write_to_any_slot.md:6 +#, fuzzy msgid "" "Nevertheless, we can use the `storage_write_syscall` and " -"`storage_read_syscall` syscalls, to write to and read from any storage slot.\n" +"`storage_read_syscall` syscalls, to write to and read from any storage slot. " "This is useful when writing to storage variables that are not known at " "compile time, or to ensure that even if the contract is upgraded and the " "computation method of storage variable addresses changes, they remain " @@ -5685,8 +2404,8 @@ msgid "" msgstr "" "然而,我们可以使用 `storage_write_syscall` 和 `storage_read_syscall` 系统调" "用,来对任何存储槽进行写入和读取。\n" -"这在写入那些在编译时还未确定的存储变量时非常有用,这也可以确保即使合约升级且存" -"储变量地址的计算方法改变,这些变量仍然可访问。" +"这在写入那些在编译时还未确定的存储变量时非常有用,这也可以确保即使合约升级且" +"存储变量地址的计算方法改变,这些变量仍然可访问。" #: src/ch02/write_to_any_slot.md:9 msgid "" @@ -5696,111 +2415,15 @@ msgid "" "onchain computations. Once the address is computed, we use the storage " "syscalls to interact with it." msgstr "" -"在以下示例中,我们使用 Poseidon 哈希函数来计算存储变量的地址。Poseidon 是一个 " -"ZK 友好的哈希函数,比 Pedersen 更便宜、更快,是链上计算的绝佳选择。一旦地址被" -"计算出来,我们就使用存储的系统调用与之交互。" +"在以下示例中,我们使用 Poseidon 哈希函数来计算存储变量的地址。Poseidon 是一" +"个 ZK 友好的哈希函数,比 Pedersen 更便宜、更快,是链上计算的绝佳选择。一旦地" +"址被计算出来,我们就使用存储的系统调用与之交互。" -#: src/ch02/write_to_any_slot.md:11 +#: src/ch02/write_to_any_slot.md:49 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IWriteToAnySlots {\n" -" fn write_slot(ref self: TContractState, value: u32);\n" -" fn read_slot(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod WriteToAnySlot {\n" -" use starknet::syscalls::{storage_read_syscall, storage_write_syscall};\n" -" use starknet::SyscallResultTrait;\n" -" use poseidon::poseidon_hash_span;\n" -" use starknet::storage_access::Felt252TryIntoStorageAddress;\n" -" use starknet::StorageAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" const SLOT_NAME: felt252 = 'test_slot';\n" -"\n" -" #[abi(embed_v0)]\n" -" impl WriteToAnySlot of super::IWriteToAnySlots {\n" -" fn write_slot(ref self: ContractState, value: u32) {\n" -" storage_write_syscall(0, get_address_from_name(SLOT_NAME), value." -"into());\n" -" }\n" -"\n" -" fn read_slot(self: @ContractState) -> u32 {\n" -" storage_read_syscall(0, get_address_from_name(SLOT_NAME))\n" -" .unwrap_syscall()\n" -" .try_into()\n" -" .unwrap()\n" -" }\n" -" }\n" -" fn get_address_from_name(variable_name: felt252) -> StorageAddress {\n" -" let mut data: Array = ArrayTrait::new();\n" -" data.append(variable_name);\n" -" let hashed_name: felt252 = poseidon_hash_span(data.span());\n" -" let MASK_250: u256 = " -"0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n" -" // By taking the 250 least significant bits of the hash output, we " -"get a valid 250bits storage address.\n" -" let result: felt252 = (hashed_name.into() & MASK_250).try_into()." -"unwrap();\n" -" let result: StorageAddress = result.try_into().unwrap();\n" -" result\n" -" }\n" -"}\n" -"```" +"// By taking the 250 least significant bits of the hash output, we get a " +"valid 250bits storage address.\n" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IWriteToAnySlots {\n" -" fn write_slot(ref self: TContractState, value: u32);\n" -" fn read_slot(self: @TContractState) -> u32;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod WriteToAnySlot {\n" -" use starknet::syscalls::{storage_read_syscall, storage_write_syscall};\n" -" use starknet::SyscallResultTrait;\n" -" use poseidon::poseidon_hash_span;\n" -" use starknet::storage_access::Felt252TryIntoStorageAddress;\n" -" use starknet::StorageAddress;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" const SLOT_NAME: felt252 = 'test_slot';\n" -"\n" -" #[abi(embed_v0)]\n" -" impl WriteToAnySlot of super::IWriteToAnySlots {\n" -" fn write_slot(ref self: ContractState, value: u32) {\n" -" storage_write_syscall(0, get_address_from_name(SLOT_NAME), value." -"into());\n" -" }\n" -"\n" -" fn read_slot(self: @ContractState) -> u32 {\n" -" storage_read_syscall(0, get_address_from_name(SLOT_NAME))\n" -" .unwrap_syscall()\n" -" .try_into()\n" -" .unwrap()\n" -" }\n" -" }\n" -" fn get_address_from_name(variable_name: felt252) -> StorageAddress {\n" -" let mut data: Array = ArrayTrait::new();\n" -" data.append(variable_name);\n" -" let hashed_name: felt252 = poseidon_hash_span(data.span());\n" -" let MASK_250: u256 = " -"0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n" -" // By taking the 250 least significant bits of the hash output, we " -"get a valid 250bits storage address.\n" -" let result: felt252 = (hashed_name.into() & MASK_250).try_into()." -"unwrap();\n" -" let result: StorageAddress = result.try_into().unwrap();\n" -" result\n" -" }\n" -"}\n" -"```" #: src/ch02/write_to_any_slot.md:56 msgid "" @@ -5818,10 +2441,6 @@ msgstr "" "blob/main/listings/ch02-advanced-concepts/write_to_any_slot/src/contract." "cairo) 中测试它." -#: src/ch02/storing_arrays.md:1 -msgid "# Storing Arrays" -msgstr "# 存储数组" - #: src/ch02/storing_arrays.md:3 msgid "" "On Starknet, complex values (e.g., tuples or structs), are stored in a " @@ -5833,180 +2452,58 @@ msgid "" "for storing arrays in Cairo, so you will need to write your own " "implementation of the `Store` trait for the type of array you wish to store." msgstr "" -"在Starknet上,复杂值(例如元组或结构体)存储在以该存储变量地址开头的连续段中。" -"复杂存储值的大小有 256 个元素的限制,这意味着要在存储中存储超过 255 个元素的数" -"组,我们需要将其分割为大小 `n <= 255` 的段,并将这些段存储在多个存储地址中。目" -"前 Cairo 没有原生支持存储数组,所以你需要为你希望存储的数组类型实现自己的 " -"`Store` 特性。" +"在Starknet上,复杂值(例如元组或结构体)存储在以该存储变量地址开头的连续段" +"中。复杂存储值的大小有 256 个元素的限制,这意味着要在存储中存储超过 255 个元" +"素的数组,我们需要将其分割为大小 `n <= 255` 的段,并将这些段存储在多个存储地" +"址中。目前 Cairo 没有原生支持存储数组,所以你需要为你希望存储的数组类型实现自" +"己的 `Store` 特性。" #: src/ch02/storing_arrays.md:5 +#, fuzzy msgid "" -"> Note: While storing arrays in storage is possible, it is not always " +"Note: While storing arrays in storage is possible, it is not always " "recommended, as the read and write operations can get very costly. For " -"example, reading an array of size `n` requires `n` storage reads, and writing " -"to an array of size `n` requires `n` storage writes. If you only need to " -"access a single element of the array at a time, it is recommended to use a " -"`LegacyMap` and store the length in another variable instead." +"example, reading an array of size `n` requires `n` storage reads, and " +"writing to an array of size `n` requires `n` storage writes. If you only " +"need to access a single element of the array at a time, it is recommended to " +"use a `LegacyMap` and store the length in another variable instead." msgstr "" -"> 注:虽然在存储中保存数组是可行的,但并不总是推荐这么做,因为读写操作的成本可" -"能非常高。例如,读取一个大小为 n 的数组需要进行 `n` 次存储读取,而向一个大小" -"为 `n` 的数组写入需要进行 `n` 次存储写入。如果你只需要一次访问数组中的一个元" -"素,建议使用 `LegacyMap` 并在另一个变量中存储数组长度。" +"> 注:虽然在存储中保存数组是可行的,但并不总是推荐这么做,因为读写操作的成本" +"可能非常高。例如,读取一个大小为 n 的数组需要进行 `n` 次存储读取,而向一个大" +"小为 `n` 的数组写入需要进行 `n` 次存储写入。如果你只需要一次访问数组中的一个" +"元素,建议使用 `LegacyMap` 并在另一个变量中存储数组长度。" #: src/ch02/storing_arrays.md:7 msgid "" "The following example demonstrates how to write a simple implementation of " -"the `StorageAccess` trait for the `Array` type, allowing us to store " -"arrays of up to 255 `felt252` elements." +"the `StorageAccess` trait for the `Array` type, allowing us to " +"store arrays of up to 255 `felt252` elements." msgstr "" "以下示例展示了如何为 `Array` 类型实现一个简单的 `StorageAccess` 特" "性,使我们能够存储多达 255 个 `felt252` 元素的数组。" -#: src/ch02/storing_arrays.md:9 +#: src/ch02/storing_arrays.md:26 msgid "" -"```rust\n" -"impl StoreFelt252Array of Store> {\n" -" fn read(address_domain: u32, base: StorageBaseAddress) -> " -"SyscallResult> {\n" -" StoreFelt252Array::read_at_offset(address_domain, base, 0)\n" -" }\n" -"\n" -" fn write(\n" -" address_domain: u32, base: StorageBaseAddress, value: Array\n" -" ) -> SyscallResult<()> {\n" -" StoreFelt252Array::write_at_offset(address_domain, base, 0, value)\n" -" }\n" -"\n" -" fn read_at_offset(\n" -" address_domain: u32, base: StorageBaseAddress, mut offset: u8\n" -" ) -> SyscallResult> {\n" -" let mut arr: Array = ArrayTrait::new();\n" -"\n" -" // Read the stored array's length. If the length is superior to 255, " -"the read will fail.\n" -" let len: u8 = Store::::read_at_offset(address_domain, base, " -"offset)\n" -" .expect('Storage Span too large');\n" -" offset += 1;\n" -"\n" -" // Sequentially read all stored elements and append them to the " -"array.\n" -" let exit = len + offset;\n" -" loop {\n" -" if offset >= exit {\n" -" break;\n" -" }\n" -"\n" -" let value = Store::::read_at_offset(address_domain, " -"base, offset).unwrap();\n" -" arr.append(value);\n" -" offset += Store::::size();\n" -" };\n" -"\n" -" // Return the array.\n" -" Result::Ok(arr)\n" -" }\n" -"\n" -" fn write_at_offset(\n" -" address_domain: u32, base: StorageBaseAddress, mut offset: u8, mut " -"value: Array\n" -" ) -> SyscallResult<()> {\n" -" // // Store the length of the array in the first storage slot.\n" -" let len: u8 = value.len().try_into().expect('Storage - Span too " -"large');\n" -" Store::::write_at_offset(address_domain, base, offset, len);\n" -" offset += 1;\n" -"\n" -" // Store the array elements sequentially\n" -" loop {\n" -" match value.pop_front() {\n" -" Option::Some(element) => {\n" -" Store::::write_at_offset(address_domain, base, " -"offset, element);\n" -" offset += Store::::size();\n" -" },\n" -" Option::None(_) => { break Result::Ok(()); }\n" -" };\n" -" }\n" -" }\n" -"\n" -" fn size() -> u8 {\n" -" 255 * Store::::size()\n" -" }\n" -"}\n" -"```" +"// Read the stored array's length. If the length is superior to 255, the " +"read will fail.\n" +msgstr "" + +#: src/ch02/storing_arrays.md:31 +msgid "" +"// Sequentially read all stored elements and append them to the array.\n" +msgstr "" + +#: src/ch02/storing_arrays.md:43 +msgid "// Return the array.\n" +msgstr "" + +#: src/ch02/storing_arrays.md:50 +msgid "// // Store the length of the array in the first storage slot.\n" +msgstr "" + +#: src/ch02/storing_arrays.md:55 +msgid "// Store the array elements sequentially\n" msgstr "" -"```rust\n" -"impl StoreFelt252Array of Store> {\n" -" fn read(address_domain: u32, base: StorageBaseAddress) -> " -"SyscallResult> {\n" -" StoreFelt252Array::read_at_offset(address_domain, base, 0)\n" -" }\n" -"\n" -" fn write(\n" -" address_domain: u32, base: StorageBaseAddress, value: Array\n" -" ) -> SyscallResult<()> {\n" -" StoreFelt252Array::write_at_offset(address_domain, base, 0, value)\n" -" }\n" -"\n" -" fn read_at_offset(\n" -" address_domain: u32, base: StorageBaseAddress, mut offset: u8\n" -" ) -> SyscallResult> {\n" -" let mut arr: Array = ArrayTrait::new();\n" -"\n" -" // Read the stored array's length. If the length is superior to 255, " -"the read will fail.\n" -" let len: u8 = Store::::read_at_offset(address_domain, base, " -"offset)\n" -" .expect('Storage Span too large');\n" -" offset += 1;\n" -"\n" -" // Sequentially read all stored elements and append them to the " -"array.\n" -" let exit = len + offset;\n" -" loop {\n" -" if offset >= exit {\n" -" break;\n" -" }\n" -"\n" -" let value = Store::::read_at_offset(address_domain, " -"base, offset).unwrap();\n" -" arr.append(value);\n" -" offset += Store::::size();\n" -" };\n" -"\n" -" // Return the array.\n" -" Result::Ok(arr)\n" -" }\n" -"\n" -" fn write_at_offset(\n" -" address_domain: u32, base: StorageBaseAddress, mut offset: u8, mut " -"value: Array\n" -" ) -> SyscallResult<()> {\n" -" // // Store the length of the array in the first storage slot.\n" -" let len: u8 = value.len().try_into().expect('Storage - Span too " -"large');\n" -" Store::::write_at_offset(address_domain, base, offset, len);\n" -" offset += 1;\n" -"\n" -" // Store the array elements sequentially\n" -" loop {\n" -" match value.pop_front() {\n" -" Option::Some(element) => {\n" -" Store::::write_at_offset(address_domain, base, " -"offset, element);\n" -" offset += Store::::size();\n" -" },\n" -" Option::None(_) => { break Result::Ok(()); }\n" -" };\n" -" }\n" -" }\n" -"\n" -" fn size() -> u8 {\n" -" 255 * Store::::size()\n" -" }\n" -"}\n" -"```" #: src/ch02/storing_arrays.md:73 msgid "" @@ -6014,66 +2511,6 @@ msgid "" "arrays in storage:" msgstr "您可以在合约中导入上面的实现方式,并使用它来在存储中存储数组:" -#: src/ch02/storing_arrays.md:75 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStoreArrayContract {\n" -" fn store_array(ref self: TContractState, arr: Array);\n" -" fn read_array(self: @TContractState) -> Array;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod StoreArrayContract {\n" -" use super::StoreFelt252Array;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" arr: Array\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StoreArrayImpl of super::IStoreArrayContract {\n" -" fn store_array(ref self: ContractState, arr: Array) {\n" -" self.arr.write(arr);\n" -" }\n" -"\n" -" fn read_array(self: @ContractState) -> Array {\n" -" self.arr.read()\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IStoreArrayContract {\n" -" fn store_array(ref self: TContractState, arr: Array);\n" -" fn read_array(self: @TContractState) -> Array;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod StoreArrayContract {\n" -" use super::StoreFelt252Array;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" arr: Array\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl StoreArrayImpl of super::IStoreArrayContract {\n" -" fn store_array(ref self: ContractState, arr: Array) {\n" -" self.arr.write(arr);\n" -" }\n" -"\n" -" fn read_array(self: @ContractState) -> Array {\n" -" self.arr.read()\n" -" }\n" -" }\n" -"}\n" -"```" - #: src/ch02/storing_arrays.md:103 msgid "" "Visit contract on [Voyager](https://goerli.voyager.online/" @@ -6086,108 +2523,35 @@ msgstr "" "contract/0x008F8069a3Fcd7691Db46Dc3b6F9D2C0436f9200E861330957Fd780A3595da86) " "上的合约,或者在 [Remix](https://remix.ethereum.org/?" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" -"blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)上" -"测试." +"blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)" +"上测试." #: src/ch02/struct-mapping-key.md:1 -msgid "# Structs as mapping keys" +#, fuzzy +msgid "Structs as mapping keys" msgstr "# 结构体作为映射键" #: src/ch02/struct-mapping-key.md:3 msgid "" -"In order to use structs as mapping keys, you can use `#[derive(Hash)]` on the " -"struct definition. This will automatically generate a hash function for the " -"struct that can be used to represent the struct as a key in a `LegacyMap`." +"In order to use structs as mapping keys, you can use `#[derive(Hash)]` on " +"the struct definition. This will automatically generate a hash function for " +"the struct that can be used to represent the struct as a key in a " +"`LegacyMap`." msgstr "" -"为了使用结构体作为映射键,您可以在结构体定义上使用 `#[derive(Hash)]`。这将为结" -"构体自动生成一个哈希函数,可以在 `LegacyMap` 中将该结构体作为键来使用。" +"为了使用结构体作为映射键,您可以在结构体定义上使用 `#[derive(Hash)]`。这将为" +"结构体自动生成一个哈希函数,可以在 `LegacyMap` 中将该结构体作为键来使用。" #: src/ch02/struct-mapping-key.md:5 +#, fuzzy msgid "" -"Consider the following example in which we would like to use an object of\n" +"Consider the following example in which we would like to use an object of " "type `Pet` as a key in a `LegacyMap`. The `Pet` struct has three fields: " "`name`, `age` and `owner`. We consider that the combination of these three " "fields uniquely identifies a pet." msgstr "" -"考虑以下示例,我们希望使用类型为 `Pet` 的对象作为 `LegacyMap` 中的键。`Pet` 结" -"构体有三个字段:`name` 、`age` 和 `owner`。假设这三个字段的组合能唯一地标识一" -"只宠物。" - -#: src/ch02/struct-mapping-key.md:8 -msgid "" -"```rust\n" -"#[derive(Copy, Drop, Serde, Hash)]\n" -"struct Pet {\n" -" name: felt252,\n" -" age: u8,\n" -" owner: felt252,\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait IPetRegistry {\n" -" fn register_pet(ref self: TContractState, key: Pet, timestamp: u64);\n" -" fn get_registration_date(self: @TContractState, key: Pet) -> u64;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod PetRegistry {\n" -" use hash::{HashStateTrait, Hash};\n" -" use super::Pet;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" registration_time: LegacyMap::,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl PetRegistry of super::IPetRegistry {\n" -" fn register_pet(ref self: ContractState, key: Pet, timestamp: u64) {\n" -" self.registration_time.write(key, timestamp);\n" -" }\n" -"\n" -" fn get_registration_date(self: @ContractState, key: Pet) -> u64 {\n" -" self.registration_time.read(key)\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[derive(Copy, Drop, Serde, Hash)]\n" -"struct Pet {\n" -" name: felt252,\n" -" age: u8,\n" -" owner: felt252,\n" -"}\n" -"\n" -"#[starknet::interface]\n" -"trait IPetRegistry {\n" -" fn register_pet(ref self: TContractState, key: Pet, timestamp: u64);\n" -" fn get_registration_date(self: @TContractState, key: Pet) -> u64;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod PetRegistry {\n" -" use hash::{HashStateTrait, Hash};\n" -" use super::Pet;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" registration_time: LegacyMap::,\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl PetRegistry of super::IPetRegistry {\n" -" fn register_pet(ref self: ContractState, key: Pet, timestamp: u64) {\n" -" self.registration_time.write(key, timestamp);\n" -" }\n" -"\n" -" fn get_registration_date(self: @ContractState, key: Pet) -> u64 {\n" -" self.registration_time.read(key)\n" -" }\n" -" }\n" -"}\n" -"```" +"考虑以下示例,我们希望使用类型为 `Pet` 的对象作为 `LegacyMap` 中的键。`Pet` " +"结构体有三个字段:`name` 、`age` 和 `owner`。假设这三个字段的组合能唯一地标识" +"一只宠物。" #: src/ch02/struct-mapping-key.md:45 msgid "" @@ -6197,12 +2561,8 @@ msgid "" "cairo)." msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." -"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-concepts/" -"struct_as_mapping_key/src/contract.cairo) 上测试这个合约." - -#: src/ch02/hash-solidity-compatible.md:1 -msgid "# Hash Solidity Compatible" -msgstr "# 兼容Hash Solidity" +"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-" +"concepts/struct_as_mapping_key/src/contract.cairo) 上测试这个合约." #: src/ch02/hash-solidity-compatible.md:3 msgid "" @@ -6213,89 +2573,21 @@ msgid "" "result with `u128_byte_reverse`." msgstr "" "这个合约展示了在 Cairo 中进行 Keccak 哈希处理以匹配 Solidity 的 keccak256。尽" -"管两者都使用 Keccak,但它们的字节序不同:Cairo 是小端序,Solidity 是大端序。该" -"合约通过使用 `keccak_u256s_be_inputs` 以大端序进行哈希处理,并使用 " +"管两者都使用 Keccak,但它们的字节序不同:Cairo 是小端序,Solidity 是大端序。" +"该合约通过使用 `keccak_u256s_be_inputs` 以大端序进行哈希处理,并使用 " "`u128_byte_reverse` 反转结果的字节来实现兼容。" -#: src/ch02/hash-solidity-compatible.md:7 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISolidityHashExample {\n" -" fn hash_data(ref self: TContractState, input_data: Span) -> u256;\n" -"}\n" -"\n" -"\n" -"#[starknet::contract]\n" -"mod SolidityHashExample {\n" -" use keccak::{keccak_u256s_be_inputs};\n" -" use array::Span;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SolidityHashExample of super::ISolidityHashExample {\n" -" fn hash_data(ref self: ContractState, input_data: Span) -> u256 " -"{\n" -" let hashed = keccak_u256s_be_inputs(input_data);\n" -"\n" -" // Split the hashed value into two 128-bit segments\n" -" let low: u128 = hashed.low;\n" -" let high: u128 = hashed.high;\n" -"\n" -" // Reverse each 128-bit segment\n" -" let reversed_low = integer::u128_byte_reverse(low);\n" -" let reversed_high = integer::u128_byte_reverse(high);\n" -"\n" -" // Reverse merge the reversed segments back into a u256 value\n" -" let compatible_hash = u256 { low: reversed_high, high: " -"reversed_low };\n" -"\n" -" compatible_hash\n" -" }\n" -" }\n" -"}\n" -"```" +#: src/ch02/hash-solidity-compatible.md:27 +msgid "// Split the hashed value into two 128-bit segments\n" +msgstr "" + +#: src/ch02/hash-solidity-compatible.md:31 +msgid "// Reverse each 128-bit segment\n" +msgstr "" + +#: src/ch02/hash-solidity-compatible.md:35 +msgid "// Reverse merge the reversed segments back into a u256 value\n" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ISolidityHashExample {\n" -" fn hash_data(ref self: TContractState, input_data: Span) -> u256;\n" -"}\n" -"\n" -"\n" -"#[starknet::contract]\n" -"mod SolidityHashExample {\n" -" use keccak::{keccak_u256s_be_inputs};\n" -" use array::Span;\n" -"\n" -" #[storage]\n" -" struct Storage {}\n" -"\n" -" #[abi(embed_v0)]\n" -" impl SolidityHashExample of super::ISolidityHashExample {\n" -" fn hash_data(ref self: ContractState, input_data: Span) -> u256 " -"{\n" -" let hashed = keccak_u256s_be_inputs(input_data);\n" -"\n" -" // Split the hashed value into two 128-bit segments\n" -" let low: u128 = hashed.low;\n" -" let high: u128 = hashed.high;\n" -"\n" -" // Reverse each 128-bit segment\n" -" let reversed_low = integer::u128_byte_reverse(low);\n" -" let reversed_high = integer::u128_byte_reverse(high);\n" -"\n" -" // Reverse merge the reversed segments back into a u256 value\n" -" let compatible_hash = u256 { low: reversed_high, high: " -"reversed_low };\n" -"\n" -" compatible_hash\n" -" }\n" -" }\n" -"}\n" -"```" #: src/ch02/hash-solidity-compatible.md:44 msgid "" @@ -6305,49 +2597,43 @@ msgid "" "contract.cairo)." msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." -"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-concepts/" -"hash_solidity_compatible/src/contract.cairo) 上测试这个合约." - -#: src/ch02/hash-solidity-compatible.md:46 -msgid "
Last change: 2023-11-21
" -msgstr "
Last change: 2023-11-21
" - -#: src/ch02/optimisations/optimisations.md:1 -msgid "# Optimisations " -msgstr "# 优化" +"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-" +"concepts/hash_solidity_compatible/src/contract.cairo) 上测试这个合约." #: src/ch02/optimisations/optimisations.md:3 msgid "A collection of optimisation patterns to save gas and steps." msgstr "这里列出了一系列优化模式,用以节省Gas和计算步骤。" #: src/ch02/optimisations/store_using_packing.md:1 -msgid "# Storage optimisation " +#, fuzzy +msgid "Storage optimisation" msgstr "# 存储优化" #: src/ch02/optimisations/store_using_packing.md:3 +#, fuzzy msgid "" "A smart contract has a limited amount of **storage slots**. Each slot can " -"store a single `felt252` value.\n" -"Writing to a storage slot has a cost, so we want to use as few storage slots " -"as possible." +"store a single `felt252` value. Writing to a storage slot has a cost, so we " +"want to use as few storage slots as possible." msgstr "" "智能合约只有有限的**存储槽位**。每个槽位可以存储一个 `felt252` 值。\n" "写入一个存储槽位会产生成本,因此我们希望尽可能少地使用存储槽位。" #: src/ch02/optimisations/store_using_packing.md:6 +#, fuzzy msgid "" "In Cairo, every type is derived from the `felt252` type, which uses 252 bits " -"to store a value.\n" -"This design is quite simple, but it does have a drawback: it is not storage " -"efficient. For example, if we want to store a `u8` value, we need to use an " -"entire slot, even though we only need 8 bits." +"to store a value. This design is quite simple, but it does have a drawback: " +"it is not storage efficient. For example, if we want to store a `u8` value, " +"we need to use an entire slot, even though we only need 8 bits." msgstr "" "在 Cairo 中,每种类型都源自 `felt252` 类型,它使用 252 位来存储一个值。\n" "这种设计相当简单,但它有一个缺点:它在存储效率方面并不高。例如,如果要存储一" "个 `u8` 值,我们需要使用整个槽位,尽管我们只需要 8 位。" #: src/ch02/optimisations/store_using_packing.md:9 -msgid "## Packing" +#, fuzzy +msgid "Packing" msgstr "## 打包" #: src/ch02/optimisations/store_using_packing.md:11 @@ -6358,19 +2644,19 @@ msgid "" "multiple values." msgstr "" "当存储多个值时,我们可以使用一种称为**打包(packing)**的技术。打包是一种允许我" -"们在单个 felt 值中存储多个值的技术。这是通过使用 felt 值的位来存储多个值来实现" -"的。" +"们在单个 felt 值中存储多个值的技术。这是通过使用 felt 值的位来存储多个值来实" +"现的。" #: src/ch02/optimisations/store_using_packing.md:13 msgid "" -"For example, if we want to store two `u8` values, we can use the first 8 bits " -"of the felt value to store the first `u8` value, and the last 8 bits to store " -"the second `u8` value. This way, we can store two `u8` values in a single " -"felt value." +"For example, if we want to store two `u8` values, we can use the first 8 " +"bits of the felt value to store the first `u8` value, and the last 8 bits to " +"store the second `u8` value. This way, we can store two `u8` values in a " +"single felt value." msgstr "" "例如,如果我们想存储两个 `u8` 值,我们可以使用 felt 值的前 8 位来存储第一个 " -"`u8` 值,而使用后 8 位来存储第二个 `u8` 值。这样,我们就可以在单个 felt 值中存" -"储两个 `u8` 值。" +"`u8` 值,而使用后 8 位来存储第二个 `u8` 值。这样,我们就可以在单个 felt 值中" +"存储两个 `u8` 值。" #: src/ch02/optimisations/store_using_packing.md:15 msgid "" @@ -6379,170 +2665,38 @@ msgid "" msgstr "" "Cairo 提供了一个内置的打包存储功能,您可以通过 `StorePacking` 特性来使用它。" -#: src/ch02/optimisations/store_using_packing.md:17 -msgid "" -"```rust\n" -"trait StorePacking {\n" -" fn pack(value: T) -> PackedT;\n" -" fn unpack(value: PackedT) -> T;\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"trait StorePacking {\n" -" fn pack(value: T) -> PackedT;\n" -" fn unpack(value: PackedT) -> T;\n" -"}\n" -"```" - #: src/ch02/optimisations/store_using_packing.md:24 msgid "" -"This allows to store the type `T` by first packing it into the type `PackedT` " -"with the `pack` function, and then storing the `PackedT` value with it's " -"`Store` implementation. When reading the value, we first retrieve the " -"`PackedT` value, and then unpack it into the type `T` using the `unpack` " +"This allows to store the type `T` by first packing it into the type " +"`PackedT` with the `pack` function, and then storing the `PackedT` value " +"with it's `Store` implementation. When reading the value, we first retrieve " +"the `PackedT` value, and then unpack it into the type `T` using the `unpack` " "function." msgstr "" "这允许通过首先使用 `pack` 函数将类型 `T` 打包成 `PackedT` 类型,然后使用其 " -"`Store` 实现来存储 `PackedT` 值。在读取值时,我们首先获取 `PackedT` 值,然后使" -"用 `unpack` 函数将其解包为类型 `T`。" +"`Store` 实现来存储 `PackedT` 值。在读取值时,我们首先获取 `PackedT` 值,然后" +"使用 `unpack` 函数将其解包为类型 `T`。" #: src/ch02/optimisations/store_using_packing.md:26 msgid "" "Here's an example of storing a `Time` struct with two `u8` values using the " "`StorePacking` trait:" msgstr "" -"以下是一个使用 `StorePacking` 特性存储包含两个 `u8` 值的 `Time` 结构体的示例:" +"以下是一个使用 `StorePacking` 特性存储包含两个 `u8` 值的 `Time` 结构体的示" +"例:" -#: src/ch02/optimisations/store_using_packing.md:28 +#: src/ch02/optimisations/store_using_packing.md:75 msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait ITime {\n" -" fn set(ref self: TContractState, value: TimeContract::Time);\n" -" fn get(self: @TContractState) -> TimeContract::Time;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod TimeContract {\n" -" use starknet::storage_access::StorePacking;\n" -" use integer::{\n" -" U8IntoFelt252, Felt252TryIntoU16, U16DivRem, u16_as_non_zero, " -"U16IntoFelt252,\n" -" Felt252TryIntoU8\n" -" };\n" -" use traits::{Into, TryInto, DivRem};\n" -" use option::OptionTrait;\n" -" use serde::Serde;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" time: Time\n" -" }\n" -"\n" -" #[derive(Copy, Serde, Drop)]\n" -" struct Time {\n" -" hour: u8,\n" -" minute: u8\n" -" }\n" -"\n" -" impl TimePackable of StorePacking {\n" -" fn pack(value: Time) -> felt252 {\n" -" let msb: felt252 = 256 * value.hour.into();\n" -" let lsb: felt252 = value.minute.into();\n" -" return msb + lsb;\n" -" }\n" -" fn unpack(value: felt252) -> Time {\n" -" let value: u16 = value.try_into().unwrap();\n" -" let (q, r) = U16DivRem::div_rem(value, u16_as_non_zero(256));\n" -" let hour: u8 = Into::::into(q).try_into()." -"unwrap();\n" -" let minute: u8 = Into::::into(r).try_into()." -"unwrap();\n" -" return Time { hour, minute };\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl TimeContract of super::ITime {\n" -" fn set(ref self: ContractState, value: Time) {\n" -" // This will call the pack method of the TimePackable trait\n" +"// This will call the pack method of the TimePackable trait\n" " // and store the resulting felt252\n" -" self.time.write(value);\n" -" }\n" -" fn get(self: @ContractState) -> Time {\n" -" // This will read the felt252 value from storage\n" -" // and return the result of the unpack method of the TimePackable " -"trait\n" -" return self.time.read();\n" -" }\n" -" }\n" -"}\n" -"```" msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait ITime {\n" -" fn set(ref self: TContractState, value: TimeContract::Time);\n" -" fn get(self: @TContractState) -> TimeContract::Time;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod TimeContract {\n" -" use starknet::storage_access::StorePacking;\n" -" use integer::{\n" -" U8IntoFelt252, Felt252TryIntoU16, U16DivRem, u16_as_non_zero, " -"U16IntoFelt252,\n" -" Felt252TryIntoU8\n" -" };\n" -" use traits::{Into, TryInto, DivRem};\n" -" use option::OptionTrait;\n" -" use serde::Serde;\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" time: Time\n" -" }\n" -"\n" -" #[derive(Copy, Serde, Drop)]\n" -" struct Time {\n" -" hour: u8,\n" -" minute: u8\n" -" }\n" -"\n" -" impl TimePackable of StorePacking {\n" -" fn pack(value: Time) -> felt252 {\n" -" let msb: felt252 = 256 * value.hour.into();\n" -" let lsb: felt252 = value.minute.into();\n" -" return msb + lsb;\n" -" }\n" -" fn unpack(value: felt252) -> Time {\n" -" let value: u16 = value.try_into().unwrap();\n" -" let (q, r) = U16DivRem::div_rem(value, u16_as_non_zero(256));\n" -" let hour: u8 = Into::::into(q).try_into()." -"unwrap();\n" -" let minute: u8 = Into::::into(r).try_into()." -"unwrap();\n" -" return Time { hour, minute };\n" -" }\n" -" }\n" -"\n" -" #[abi(embed_v0)]\n" -" impl TimeContract of super::ITime {\n" -" fn set(ref self: ContractState, value: Time) {\n" -" // This will call the pack method of the TimePackable trait\n" -" // and store the resulting felt252\n" -" self.time.write(value);\n" -" }\n" -" fn get(self: @ContractState) -> Time {\n" -" // This will read the felt252 value from storage\n" -" // and return the result of the unpack method of the TimePackable " -"trait\n" -" return self.time.read();\n" -" }\n" -" }\n" -"}\n" -"```" + +#: src/ch02/optimisations/store_using_packing.md:80 +msgid "" +"// This will read the felt252 value from storage\n" +" // and return the result of the unpack method of the " +"TimePackable trait\n" +msgstr "" #: src/ch02/optimisations/store_using_packing.md:88 msgid "" @@ -6553,12 +2707,8 @@ msgid "" msgstr "" "在 [Remix](https://remix.ethereum.org/?#activate=Starknet-cairo1-" "compiler&url=https://github.com/NethermindEth/StarknetByExample/blob/main/" -"listings/ch02-advanced-concepts/store_using_packing/src/contract.cairo) 上测试" -"这个合约." - -#: src/ch02/list.md:1 -msgid "# List" -msgstr "# 列表" +"listings/ch02-advanced-concepts/store_using_packing/src/contract.cairo) 上测" +"试这个合约." #: src/ch02/list.md:3 msgid "" @@ -6571,59 +2721,19 @@ msgstr "" "main/src/storage) 获取更多详细信息。" #: src/ch02/list.md:5 -msgid "## What is `List`?" +#, fuzzy +msgid "What is `List`?" msgstr "## `List`是什么?" #: src/ch02/list.md:7 msgid "An ordered sequence of values that can be used in Starknet storage:" msgstr "可以在 Starknet 存储中使用的有序值序列:" -#: src/ch02/list.md:9 -msgid "" -"```rust\n" -"#[storage]\n" -"stuct Storage {\n" -" amounts: List\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[storage]\n" -"stuct Storage {\n" -" amounts: List\n" -"}\n" -"```" - #: src/ch02/list.md:16 -msgid "### Interface" +#, fuzzy +msgid "Interface" msgstr "### 接口" -#: src/ch02/list.md:18 -msgid "" -"```rust\n" -"trait ListTrait {\n" -" fn len(self: @List) -> u32;\n" -" fn is_empty(self: @List) -> bool;\n" -" fn append(ref self: List, value: T) -> u32;\n" -" fn get(self: @List, index: u32) -> Option;\n" -" fn set(ref self: List, index: u32, value: T);\n" -" fn pop_front(ref self: List) -> Option;\n" -" fn array(self: @List) -> Array;\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"trait ListTrait {\n" -" fn len(self: @List) -> u32;\n" -" fn is_empty(self: @List) -> bool;\n" -" fn append(ref self: List, value: T) -> u32;\n" -" fn get(self: @List, index: u32) -> Option;\n" -" fn set(ref self: List, index: u32, value: T);\n" -" fn pop_front(ref self: List) -> Option;\n" -" fn array(self: @List) -> Array;\n" -"}\n" -"```" - #: src/ch02/list.md:30 msgid "" "`List` also implements `IndexView` so you can use the familiar bracket " @@ -6631,16 +2741,6 @@ msgid "" msgstr "" "`List` 还实现了 `IndexView`,因此您可以使用熟悉的方括号表示法来访问其成员:" -#: src/ch02/list.md:32 -msgid "" -"```rust\n" -"let second = self.amounts.read()[1];\n" -"```" -msgstr "" -"```rust\n" -"let second = self.amounts.read()[1];\n" -"```" - #: src/ch02/list.md:36 msgid "" "Note that unlike `get`, using this bracket notation panics when accessing an " @@ -6650,7 +2750,8 @@ msgstr "" "(崩溃)。" #: src/ch02/list.md:38 -msgid "### Support for custom types" +#, fuzzy +msgid "Support for custom types" msgstr "### 支持自定义类型" #: src/ch02/list.md:40 @@ -6660,12 +2761,13 @@ msgid "" "trait. You can have the compiler derive it for you using the " "`#[derive(starknet::Store)]` attribute." msgstr "" -"`List` 默认支持大多数 corelib 类型。如果您想在 `List` 中存储自己的自定义类型," -"该类型必须实现 `Store` 特性。您可以使用 `#[derive(starknet::Store)]` 属性让编" -"译器自动生成。" +"`List` 默认支持大多数 corelib 类型。如果您想在 `List` 中存储自己的自定义类" +"型,该类型必须实现 `Store` 特性。您可以使用 `#[derive(starknet::Store)]` 属性" +"让编译器自动生成。" #: src/ch02/list.md:42 -msgid "### Caveats" +#, fuzzy +msgid "Caveats" msgstr "### 注意事项" #: src/ch02/list.md:44 @@ -6674,45 +2776,34 @@ msgstr "在使用 `List` 时,有两个特点应该注意:" #: src/ch02/list.md:46 msgid "" -"1. The `append` operation costs 2 storage writes - one for the value itself " -"and another one for updating the List's length\n" -"2. Due to a compiler limitation, it is not possible to use mutating " -"operations with a single inline statement. For example, `self.amounts.read()." -"append(42);` will not work. You have to do it in 2 steps:" +"The `append` operation costs 2 storage writes - one for the value itself and " +"another one for updating the List's length" msgstr "" -"1. `append` 操作消耗 2 次存储写入操作 - 一次是为了值本身,另一次是为了更新列表" -"的长度。\n" -"2. 由于编译器的限制,不能使用单个内联语句进行变更操作。例如,`self.amounts." -"read().append(42);` 是不行的。你必须分两步进行:" -#: src/ch02/list.md:49 +#: src/ch02/list.md:47 +#, fuzzy msgid "" -"```rust\n" -"let mut amounts = self.amounts.read();\n" -"amounts.append(42);\n" -"```" +"Due to a compiler limitation, it is not possible to use mutating operations " +"with a single inline statement. For example, `self.amounts.read().append(42);" +"` will not work. You have to do it in 2 steps:" msgstr "" -"```rust\n" -"let mut amounts = self.amounts.read();\n" -"amounts.append(42);\n" -"```" +"1. `append` 操作消耗 2 次存储写入操作 - 一次是为了值本身,另一次是为了更新列" +"表的长度。\n" +"2. 由于编译器的限制,不能使用单个内联语句进行变更操作。例如,`self.amounts." +"read().append(42);` 是不行的。你必须分两步进行:" #: src/ch02/list.md:54 -msgid "### Dependencies" +#, fuzzy +msgid "Dependencies" msgstr "### 依赖关系" #: src/ch02/list.md:56 msgid "Update your project dependencies by in the `Scarb.toml` file:" msgstr "在 `Scarb.toml` 里更新您项目的依赖:" -#: src/ch02/list.md:57 -msgid "" -"```rust\n" -"[dependencies]\n" -"(...)\n" -"alexandria_storage = { git = \"https://github.com/keep-starknet-strange/" -"alexandria.git\" }\n" -"```" +#: src/ch02/list.md:60 +#, fuzzy +msgid "\"https://github.com/keep-starknet-strange/alexandria.git\"" msgstr "" "```rust\n" "[dependencies]\n" @@ -6727,166 +2818,4784 @@ msgid "" "amounts and tasks:" msgstr "例如,我们用 `List` 来创建一个跟踪`amount`和`tasks`的合约:" -#: src/ch02/list.md:65 -msgid "" -"```rust\n" -"#[starknet::interface]\n" -"trait IListExample {\n" -" fn add_in_amount(ref self: TContractState, number: u128);\n" -" fn add_in_task(ref self: TContractState, description: felt252, status: " -"felt252);\n" -" fn is_empty_list(self: @TContractState) -> bool;\n" -" fn list_length(self: @TContractState) -> u32;\n" -" fn get_from_index(self: @TContractState, index: u32) -> u128;\n" -" fn set_from_index(ref self: TContractState, index: u32, number: u128);\n" -" fn pop_front_list(ref self: TContractState);\n" -" fn array_conversion(self: @TContractState) -> Array;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ListExample {\n" -" use alexandria_storage::list::{List, ListTrait};\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" amount: List,\n" -" tasks: List\n" -" }\n" -"\n" -" #[derive(Copy, Drop, Serde, starknet::Store)]\n" -" struct Task {\n" -" description: felt252,\n" -" status: felt252\n" -" }\n" -"\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ListExample of super::IListExample {\n" -" fn add_in_amount(ref self: ContractState, number: u128) {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.append(number);\n" -" }\n" -"\n" -" fn add_in_task(ref self: ContractState, description: felt252, status: " -"felt252) {\n" -" let new_task = Task { description: description, status: " -"status };\n" -" let mut current_tasks_list = self.tasks.read();\n" -" current_tasks_list.append(new_task);\n" -" }\n" -"\n" -" fn is_empty_list(self: @ContractState) -> bool {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.is_empty()\n" -" }\n" -"\n" -" fn list_length(self: @ContractState) -> u32 {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.len()\n" -" }\n" -"\n" -" fn get_from_index(self: @ContractState, index: u32) -> u128 {\n" -" self.amount.read()[index]\n" -" }\n" -"\n" -" fn set_from_index(ref self: ContractState, index: u32, number: u128) " -"{\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.set(index, number);\n" -" }\n" -"\n" -" fn pop_front_list(ref self: ContractState) {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.pop_front();\n" -" }\n" -"\n" -" fn array_conversion(self: @ContractState) -> Array {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.array()\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" -"```rust\n" -"#[starknet::interface]\n" -"trait IListExample {\n" -" fn add_in_amount(ref self: TContractState, number: u128);\n" -" fn add_in_task(ref self: TContractState, description: felt252, status: " -"felt252);\n" -" fn is_empty_list(self: @TContractState) -> bool;\n" -" fn list_length(self: @TContractState) -> u32;\n" -" fn get_from_index(self: @TContractState, index: u32) -> u128;\n" -" fn set_from_index(ref self: TContractState, index: u32, number: u128);\n" -" fn pop_front_list(ref self: TContractState);\n" -" fn array_conversion(self: @TContractState) -> Array;\n" -"}\n" -"\n" -"#[starknet::contract]\n" -"mod ListExample {\n" -" use alexandria_storage::list::{List, ListTrait};\n" -"\n" -" #[storage]\n" -" struct Storage {\n" -" amount: List,\n" -" tasks: List\n" -" }\n" -"\n" -" #[derive(Copy, Drop, Serde, starknet::Store)]\n" -" struct Task {\n" -" description: felt252,\n" -" status: felt252\n" -" }\n" -"\n" -"\n" -" #[abi(embed_v0)]\n" -" impl ListExample of super::IListExample {\n" -" fn add_in_amount(ref self: ContractState, number: u128) {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.append(number);\n" -" }\n" -"\n" -" fn add_in_task(ref self: ContractState, description: felt252, status: " -"felt252) {\n" -" let new_task = Task { description: description, status: " -"status };\n" -" let mut current_tasks_list = self.tasks.read();\n" -" current_tasks_list.append(new_task);\n" -" }\n" -"\n" -" fn is_empty_list(self: @ContractState) -> bool {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.is_empty()\n" -" }\n" -"\n" -" fn list_length(self: @ContractState) -> u32 {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.len()\n" -" }\n" -"\n" -" fn get_from_index(self: @ContractState, index: u32) -> u128 {\n" -" self.amount.read()[index]\n" -" }\n" -"\n" -" fn set_from_index(ref self: ContractState, index: u32, number: u128) " -"{\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.set(index, number);\n" -" }\n" -"\n" -" fn pop_front_list(ref self: ContractState) {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.pop_front();\n" -" }\n" -"\n" -" fn array_conversion(self: @ContractState) -> Array {\n" -" let mut current_amount_list = self.amount.read();\n" -" current_amount_list.array()\n" -" }\n" -" }\n" -"}\n" -"```" - -#: src/ch02/list.md:139 -msgid "
Last change: 2023-11-27
" -msgstr "
Last change: 2023-11-27
" +#~ msgid "" +#~ "- [Starklings](https://github.com/shramee/starklings-cairo1): An " +#~ "interactive tutorial to get you up and running with Cairo v1 and " +#~ "Starknet \n" +#~ "- [Cairopractice](https://cairopractice.com/): A blog with a series of " +#~ "articles about Cairo and Starknet\n" +#~ "- [Cairo by example](https://cairo-by-example.com/): An introduction to " +#~ "Cairo, with simple examples" +#~ msgstr "" +#~ "- [Starklings](https://github.com/shramee/starklings-cairo1):让您使用 " +#~ "Cairo v1 和Starknet互动的教程\n" +#~ "- [Cairopractice](https://cairopractice.com/):关于Cairo和Starknet的一系列" +#~ "文章的博客\n" +#~ "- [Cairo by example](https://cairo-by-example.com/):Cairo 简介,附带简单" +#~ "示例" + +#~ msgid "
Last change: 2023-11-30
" +#~ msgstr "
Last change: 2023-11-30
" + +#~ msgid "
Last change: 2023-10-12
" +#~ msgstr "
Last change: 2023-10-12
" + +#~ msgid "# Storage" +#~ msgstr "# 存储" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod Contract {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod Contract {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod Contract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " a: u128,\n" +#~ " b: u8,\n" +#~ " c: u256\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod Contract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " a: u128,\n" +#~ " b: u8,\n" +#~ " c: u256\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-11-20
" +#~ msgstr "
Last change: 2023-11-20
" + +#~ msgid "# Constructor" +#~ msgstr "# 构造函数" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod ExampleConstructor {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " names: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " // The constructor is decorated with a `#[constructor]` attribute.\n" +#~ " // It is not inside an `impl` block.\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, name: felt252, address: " +#~ "ContractAddress) {\n" +#~ " self.names.write(address, name);\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod ExampleConstructor {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " names: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " // The constructor is decorated with a `#[constructor]` attribute.\n" +#~ " // It is not inside an `impl` block.\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, name: felt252, address: " +#~ "ContractAddress) {\n" +#~ " self.names.write(address, name);\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Variables" +#~ msgstr "# 变量" + +#~ msgid "" +#~ "- Local\n" +#~ " - declared inside a function\n" +#~ " - not stored on the blockchain\n" +#~ "- Storage\n" +#~ " - declared in the [Storage](./storage.md) of a contract\n" +#~ " - can be accessed from one execution to another\n" +#~ "- Global\n" +#~ " - provides information about the blockchain\n" +#~ " - accessed anywhere, even within library functions" +#~ msgstr "" +#~ "- 局部\n" +#~ " - 在函数中声明\n" +#~ " - 不存储在区块链中\n" +#~ "- 存储\n" +#~ " - 在合约的 [Storage](./storage.md) 中声明\n" +#~ " - 可从一个执行过程访问到另一个执行过程\n" +#~ "- 全局\n" +#~ " - 提供有关区块链的信息\n" +#~ " - 可在任何地方访问,甚至在库函数中" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ILocalVariablesExample {\n" +#~ " fn do_something(self: @TContractState, value: u32) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod LocalVariablesExample {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl LocalVariablesExample of super::" +#~ "ILocalVariablesExample {\n" +#~ " fn do_something(self: @ContractState, value: u32) -> u32 {\n" +#~ " // This variable is local to the current block. It can't be " +#~ "accessed once it goes out of scope.\n" +#~ " let increment = 10;\n" +#~ "\n" +#~ " {\n" +#~ " // The scope of a code block allows for local variable " +#~ "declaration\n" +#~ " // We can access variables defined in higher scopes.\n" +#~ " let sum = value + increment;\n" +#~ " sum\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ILocalVariablesExample {\n" +#~ " fn do_something(self: @TContractState, value: u32) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod LocalVariablesExample {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl LocalVariablesExample of super::" +#~ "ILocalVariablesExample {\n" +#~ " fn do_something(self: @ContractState, value: u32) -> u32 {\n" +#~ " // This variable is local to the current block. It can't be " +#~ "accessed once it goes out of scope.\n" +#~ " let increment = 10;\n" +#~ "\n" +#~ " {\n" +#~ " // The scope of a code block allows for local variable " +#~ "declaration\n" +#~ " // We can access variables defined in higher scopes.\n" +#~ " let sum = value + increment;\n" +#~ " sum\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStorageVariableExample {\n" +#~ " fn set(ref self: TContractState, value: u32);\n" +#~ " fn get(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod StorageVariablesExample {\n" +#~ " // All storage variables are contained in a struct called Storage\n" +#~ " // annotated with the `#[storage]` attribute\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Storage variable holding a number\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StorageVariablesExample of super::" +#~ "IStorageVariableExample {\n" +#~ " // Write to storage variables by sending a transaction that calls " +#~ "an external function\n" +#~ " fn set(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ "\n" +#~ " // Read from storage variables without sending transactions\n" +#~ " fn get(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStorageVariableExample {\n" +#~ " fn set(ref self: TContractState, value: u32);\n" +#~ " fn get(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod StorageVariablesExample {\n" +#~ " // All storage variables are contained in a struct called Storage\n" +#~ " // annotated with the `#[storage]` attribute\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Storage variable holding a number\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StorageVariablesExample of super::" +#~ "IStorageVariableExample {\n" +#~ " // Write to storage variables by sending a transaction that calls " +#~ "an external function\n" +#~ " fn set(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ "\n" +#~ " // Read from storage variables without sending transactions\n" +#~ " fn get(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IGlobalExample {\n" +#~ " fn foo(ref self: TContractState);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod GlobalExample {\n" +#~ " // import the required functions from the starknet core library\n" +#~ " use starknet::get_caller_address;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl GlobalExampleImpl of super::IGlobalExample {\n" +#~ " fn foo(ref self: ContractState) {\n" +#~ " // Call the get_caller_address function to get the sender " +#~ "address\n" +#~ " let caller = get_caller_address();\n" +#~ " // ...\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IGlobalExample {\n" +#~ " fn foo(ref self: TContractState);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod GlobalExample {\n" +#~ " // import the required functions from the starknet core library\n" +#~ " use starknet::get_caller_address;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl GlobalExampleImpl of super::IGlobalExample {\n" +#~ " fn foo(ref self: ContractState) {\n" +#~ " // Call the get_caller_address function to get the sender " +#~ "address\n" +#~ " let caller = get_caller_address();\n" +#~ " // ...\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Visibility and Mutability" +#~ msgstr "# 可见性和可变性" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IExampleContract {\n" +#~ " fn set(ref self: TContractState, value: u32);\n" +#~ " fn get(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ExampleContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ "\n" +#~ " // The `abi(embed_v0)` attribute indicates that all the functions in " +#~ "this implementation can be called externally.\n" +#~ " // Omitting this attribute would make all the functions in this " +#~ "implementation internal.\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ExampleContract of super::IExampleContract {\n" +#~ " // The `set` function can be called externally because it is " +#~ "written inside an implementation marked as `#[external]`.\n" +#~ " // It can modify the contract's state as it is passed as a " +#~ "reference.\n" +#~ " fn set(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ "\n" +#~ " // The `get` function can be called externally because it is " +#~ "written inside an implementation marked as `#[external]`.\n" +#~ " // However, it can't modify the contract's state is passed as a " +#~ "snapshot: it is only a \"view\" function.\n" +#~ " fn get(self: @ContractState) -> u32 {\n" +#~ " // We can call an internal function from any functions within " +#~ "the contract\n" +#~ " PrivateFunctionsTrait::_read_value(self)\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " // The lack of the `external` attribute indicates that all the " +#~ "functions in this implementation can only be called internally.\n" +#~ " // We name the trait `PrivateFunctionsTrait` to indicate that it is " +#~ "an internal trait allowing us to call internal functions.\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " // The `_read_value` function is outside the implementation that " +#~ "is marked as `#[abi(embed_v0)]`, so it's an _internal_ function\n" +#~ " // and can only be called from within the contract.\n" +#~ " // However, it can't modify the contract's state is passed as a " +#~ "snapshot: it is only a \"view\" function.\n" +#~ " fn _read_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IExampleContract {\n" +#~ " fn set(ref self: TContractState, value: u32);\n" +#~ " fn get(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ExampleContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ "\n" +#~ " // The `abi(embed_v0)` attribute indicates that all the functions in " +#~ "this implementation can be called externally.\n" +#~ " // Omitting this attribute would make all the functions in this " +#~ "implementation internal.\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ExampleContract of super::IExampleContract {\n" +#~ " // The `set` function can be called externally because it is " +#~ "written inside an implementation marked as `#[external]`.\n" +#~ " // It can modify the contract's state as it is passed as a " +#~ "reference.\n" +#~ " fn set(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ "\n" +#~ " // The `get` function can be called externally because it is " +#~ "written inside an implementation marked as `#[external]`.\n" +#~ " // However, it can't modify the contract's state is passed as a " +#~ "snapshot: it is only a \"view\" function.\n" +#~ " fn get(self: @ContractState) -> u32 {\n" +#~ " // We can call an internal function from any functions within " +#~ "the contract\n" +#~ " PrivateFunctionsTrait::_read_value(self)\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " // The lack of the `external` attribute indicates that all the " +#~ "functions in this implementation can only be called internally.\n" +#~ " // We name the trait `PrivateFunctionsTrait` to indicate that it is " +#~ "an internal trait allowing us to call internal functions.\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " // The `_read_value` function is outside the implementation that " +#~ "is marked as `#[abi(embed_v0)]`, so it's an _internal_ function\n" +#~ " // and can only be called from within the contract.\n" +#~ " // However, it can't modify the contract's state is passed as a " +#~ "snapshot: it is only a \"view\" function.\n" +#~ " fn _read_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-10-19
" +#~ msgstr "
Last change: 2023-10-19
" + +#~ msgid "" +#~ "- The contract has a state variable called 'counter' that is initialized " +#~ "to 0.\n" +#~ "\n" +#~ "- When a user calls 'increment', the contract increments the counter by " +#~ "1.\n" +#~ "\n" +#~ "- When a user calls 'decrement', the contract decrements the counter by 1." +#~ msgstr "" +#~ "- 合约有一个名为 'counter'的状态变量,初始化为 0。\n" +#~ "\n" +#~ "- 当用户调用 'increment'时,合约会将计数器递增 1。\n" +#~ "\n" +#~ "- 当用户调用 'decrement'时,合约会将计数器递减 1。" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleCounter {\n" +#~ " fn get_current_count(self: @TContractState) -> u128;\n" +#~ " fn increment(ref self: TContractState);\n" +#~ " fn decrement(ref self: TContractState);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleCounter {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Counter variable\n" +#~ " counter: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, init_value: u128) {\n" +#~ " // Store initial value\n" +#~ " self.counter.write(init_value);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleCounter of super::ISimpleCounter {\n" +#~ " fn get_current_count(self: @ContractState) -> u128 {\n" +#~ " return self.counter.read();\n" +#~ " }\n" +#~ "\n" +#~ " fn increment(ref self: ContractState) {\n" +#~ " // Store counter value + 1\n" +#~ " let counter = self.counter.read() + 1;\n" +#~ " self.counter.write(counter);\n" +#~ " }\n" +#~ " fn decrement(ref self: ContractState) {\n" +#~ " // Store counter value - 1\n" +#~ " let counter = self.counter.read() - 1;\n" +#~ " self.counter.write(counter);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleCounter {\n" +#~ " fn get_current_count(self: @TContractState) -> u128;\n" +#~ " fn increment(ref self: TContractState);\n" +#~ " fn decrement(ref self: TContractState);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleCounter {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Counter variable\n" +#~ " counter: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, init_value: u128) {\n" +#~ " // Store initial value\n" +#~ " self.counter.write(init_value);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleCounter of super::ISimpleCounter {\n" +#~ " fn get_current_count(self: @ContractState) -> u128 {\n" +#~ " return self.counter.read();\n" +#~ " }\n" +#~ "\n" +#~ " fn increment(ref self: ContractState) {\n" +#~ " // Store counter value + 1\n" +#~ " let counter = self.counter.read() + 1;\n" +#~ " self.counter.write(counter);\n" +#~ " }\n" +#~ " fn decrement(ref self: ContractState) {\n" +#~ " // Store counter value - 1\n" +#~ " let counter = self.counter.read() - 1;\n" +#~ " self.counter.write(counter);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-11-04
" +#~ msgstr "
Last change: 2023-11-04
" + +#~ msgid "# Mappings" +#~ msgstr "# 映射" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IMapContract {\n" +#~ " fn set(ref self: TContractState, key: ContractAddress, value: " +#~ "felt252);\n" +#~ " fn get(self: @TContractState, key: ContractAddress) -> felt252;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod MapContract {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // The `LegacyMap` type is only available inside the `Storage` " +#~ "struct.\n" +#~ " map: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl MapContractImpl of super::IMapContract {\n" +#~ " fn set(ref self: ContractState, key: ContractAddress, value: " +#~ "felt252) {\n" +#~ " self.map.write(key, value);\n" +#~ " }\n" +#~ "\n" +#~ " fn get(self: @ContractState, key: ContractAddress) -> felt252 {\n" +#~ " self.map.read(key)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IMapContract {\n" +#~ " fn set(ref self: TContractState, key: ContractAddress, value: " +#~ "felt252);\n" +#~ " fn get(self: @TContractState, key: ContractAddress) -> felt252;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod MapContract {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // The `LegacyMap` type is only available inside the `Storage` " +#~ "struct.\n" +#~ " map: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl MapContractImpl of super::IMapContract {\n" +#~ " fn set(ref self: ContractState, key: ContractAddress, value: " +#~ "felt252) {\n" +#~ " self.map.write(key, value);\n" +#~ " }\n" +#~ "\n" +#~ " fn get(self: @ContractState, key: ContractAddress) -> felt252 {\n" +#~ " self.map.read(key)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Errors" +#~ msgstr "# 错误" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IErrorsExample {\n" +#~ " fn test_assert(self: @TContractState, i: u256);\n" +#~ " fn test_panic(self: @TContractState, i: u256);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod ErrorsExample {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ErrorsExample of super::IErrorsExample {\n" +#~ " fn test_assert(self: @ContractState, i: u256) {\n" +#~ " // Assert used to validate a condition\n" +#~ " // and abort execution if the condition is not met\n" +#~ " assert(i > 0, 'i must be greater than 0');\n" +#~ " }\n" +#~ "\n" +#~ " fn test_panic(self: @ContractState, i: u256) {\n" +#~ " if (i == 0) {\n" +#~ " // Panic used to abort execution directly\n" +#~ " panic_with_felt252('i must not be 0');\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IErrorsExample {\n" +#~ " fn test_assert(self: @TContractState, i: u256);\n" +#~ " fn test_panic(self: @TContractState, i: u256);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod ErrorsExample {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ErrorsExample of super::IErrorsExample {\n" +#~ " fn test_assert(self: @ContractState, i: u256) {\n" +#~ " // Assert used to validate a condition\n" +#~ " // and abort execution if the condition is not met\n" +#~ " assert(i > 0, 'i must be greater than 0');\n" +#~ " }\n" +#~ "\n" +#~ " fn test_panic(self: @ContractState, i: u256) {\n" +#~ " if (i == 0) {\n" +#~ " // Panic used to abort execution directly\n" +#~ " panic_with_felt252('i must not be 0');\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "mod Errors {\n" +#~ " const NOT_POSITIVE: felt252 = 'must be greater than 0';\n" +#~ " const NOT_NULL: felt252 = 'must not be null';\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICustomErrorsExample {\n" +#~ " fn test_assert(self: @TContractState, i: u256);\n" +#~ " fn test_panic(self: @TContractState, i: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod CustomErrorsExample {\n" +#~ " use super::Errors;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl CustomErrorsExample of super::" +#~ "ICustomErrorsExample {\n" +#~ " fn test_assert(self: @ContractState, i: u256) {\n" +#~ " assert(i > 0, Errors::NOT_POSITIVE);\n" +#~ " }\n" +#~ "\n" +#~ " fn test_panic(self: @ContractState, i: u256) {\n" +#~ " if (i == 0) {\n" +#~ " panic_with_felt252(Errors::NOT_NULL);\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "mod Errors {\n" +#~ " const NOT_POSITIVE: felt252 = 'must be greater than 0';\n" +#~ " const NOT_NULL: felt252 = 'must not be null';\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICustomErrorsExample {\n" +#~ " fn test_assert(self: @TContractState, i: u256);\n" +#~ " fn test_panic(self: @TContractState, i: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod CustomErrorsExample {\n" +#~ " use super::Errors;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl CustomErrorsExample of super::" +#~ "ICustomErrorsExample {\n" +#~ " fn test_assert(self: @ContractState, i: u256) {\n" +#~ " assert(i > 0, Errors::NOT_POSITIVE);\n" +#~ " }\n" +#~ "\n" +#~ " fn test_panic(self: @ContractState, i: u256) {\n" +#~ " if (i == 0) {\n" +#~ " panic_with_felt252(Errors::NOT_NULL);\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "mod VaultErrors {\n" +#~ " const INSUFFICIENT_BALANCE: felt252 = 'insufficient_balance';\n" +#~ "// you can define more errors here\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IVaultErrorsExample {\n" +#~ " fn deposit(ref self: TContractState, amount: u256);\n" +#~ " fn withdraw(ref self: TContractState, amount: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod VaultErrorsExample {\n" +#~ " use super::VaultErrors;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " balance: u256,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl VaultErrorsExample of super::IVaultErrorsExample " +#~ "{\n" +#~ " fn deposit(ref self: ContractState, amount: u256) {\n" +#~ " let mut balance = self.balance.read();\n" +#~ " balance = balance + amount;\n" +#~ " self.balance.write(balance);\n" +#~ " }\n" +#~ "\n" +#~ " fn withdraw(ref self: ContractState, amount: u256) {\n" +#~ " let mut balance = self.balance.read();\n" +#~ "\n" +#~ " assert(balance >= amount, VaultErrors::" +#~ "INSUFFICIENT_BALANCE);\n" +#~ "\n" +#~ " // Or using panic:\n" +#~ " if (balance >= amount) {\n" +#~ " panic_with_felt252(VaultErrors::INSUFFICIENT_BALANCE);\n" +#~ " }\n" +#~ "\n" +#~ " let balance = balance - amount;\n" +#~ "\n" +#~ " self.balance.write(balance);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "mod VaultErrors {\n" +#~ " const INSUFFICIENT_BALANCE: felt252 = 'insufficient_balance';\n" +#~ "// you can define more errors here\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IVaultErrorsExample {\n" +#~ " fn deposit(ref self: TContractState, amount: u256);\n" +#~ " fn withdraw(ref self: TContractState, amount: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod VaultErrorsExample {\n" +#~ " use super::VaultErrors;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " balance: u256,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl VaultErrorsExample of super::IVaultErrorsExample " +#~ "{\n" +#~ " fn deposit(ref self: ContractState, amount: u256) {\n" +#~ " let mut balance = self.balance.read();\n" +#~ " balance = balance + amount;\n" +#~ " self.balance.write(balance);\n" +#~ " }\n" +#~ "\n" +#~ " fn withdraw(ref self: ContractState, amount: u256) {\n" +#~ " let mut balance = self.balance.read();\n" +#~ "\n" +#~ " assert(balance >= amount, VaultErrors::" +#~ "INSUFFICIENT_BALANCE);\n" +#~ "\n" +#~ " // Or using panic:\n" +#~ " if (balance >= amount) {\n" +#~ " panic_with_felt252(VaultErrors::INSUFFICIENT_BALANCE);\n" +#~ " }\n" +#~ "\n" +#~ " let balance = balance - amount;\n" +#~ "\n" +#~ " self.balance.write(balance);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Events" +#~ msgstr "# 事件" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IEventCounter {\n" +#~ " fn increment(ref self: TContractState);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod EventCounter {\n" +#~ " use starknet::{get_caller_address, ContractAddress};\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Counter value\n" +#~ " counter: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " // The event enum must be annotated with the `#[event]` attribute.\n" +#~ " // It must also derive the `Drop` and `starknet::Event` traits.\n" +#~ " enum Event {\n" +#~ " CounterIncreased: CounterIncreased,\n" +#~ " UserIncreaseCounter: UserIncreaseCounter\n" +#~ " }\n" +#~ "\n" +#~ " // By deriving the `starknet::Event` trait, we indicate to the " +#~ "compiler that\n" +#~ " // this struct will be used when emitting events.\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct CounterIncreased {\n" +#~ " amount: u128\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct UserIncreaseCounter {\n" +#~ " // The `#[key]` attribute indicates that this event will be " +#~ "indexed.\n" +#~ " #[key]\n" +#~ " user: ContractAddress,\n" +#~ " new_value: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl EventCounter of super::IEventCounter {\n" +#~ " fn increment(ref self: ContractState) {\n" +#~ " let mut counter = self.counter.read();\n" +#~ " counter += 1;\n" +#~ " self.counter.write(counter);\n" +#~ " // Emit event\n" +#~ " self.emit(Event::CounterIncreased(CounterIncreased { amount: " +#~ "1 }));\n" +#~ " self\n" +#~ " .emit(\n" +#~ " Event::UserIncreaseCounter(\n" +#~ " UserIncreaseCounter {\n" +#~ " user: get_caller_address(), new_value: self." +#~ "counter.read()\n" +#~ " }\n" +#~ " )\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IEventCounter {\n" +#~ " fn increment(ref self: TContractState);\n" +#~ "}\n" +#~ "#[starknet::contract]\n" +#~ "mod EventCounter {\n" +#~ " use starknet::{get_caller_address, ContractAddress};\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " // Counter value\n" +#~ " counter: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " // The event enum must be annotated with the `#[event]` attribute.\n" +#~ " // It must also derive the `Drop` and `starknet::Event` traits.\n" +#~ " enum Event {\n" +#~ " CounterIncreased: CounterIncreased,\n" +#~ " UserIncreaseCounter: UserIncreaseCounter\n" +#~ " }\n" +#~ "\n" +#~ " // By deriving the `starknet::Event` trait, we indicate to the " +#~ "compiler that\n" +#~ " // this struct will be used when emitting events.\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct CounterIncreased {\n" +#~ " amount: u128\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct UserIncreaseCounter {\n" +#~ " // The `#[key]` attribute indicates that this event will be " +#~ "indexed.\n" +#~ " #[key]\n" +#~ " user: ContractAddress,\n" +#~ " new_value: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl EventCounter of super::IEventCounter {\n" +#~ " fn increment(ref self: ContractState) {\n" +#~ " let mut counter = self.counter.read();\n" +#~ " counter += 1;\n" +#~ " self.counter.write(counter);\n" +#~ " // Emit event\n" +#~ " self.emit(Event::CounterIncreased(CounterIncreased { amount: " +#~ "1 }));\n" +#~ " self\n" +#~ " .emit(\n" +#~ " Event::UserIncreaseCounter(\n" +#~ " UserIncreaseCounter {\n" +#~ " user: get_caller_address(), new_value: self." +#~ "counter.read()\n" +#~ " }\n" +#~ " )\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Storing Custom Types" +#~ msgstr "# 存储自定义类型" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStoringCustomType {\n" +#~ " fn set_person(ref self: TContractState, person: Person);\n" +#~ "}\n" +#~ "\n" +#~ "// Deriving the starknet::Store trait\n" +#~ "// allows us to store the `Person` struct in the contract's storage.\n" +#~ "#[derive(Drop, Serde, Copy, starknet::Store)]\n" +#~ "struct Person {\n" +#~ " age: u8,\n" +#~ " name: felt252\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod StoringCustomType {\n" +#~ " use super::Person;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " person: Person\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StoringCustomType of super::IStoringCustomType {\n" +#~ " fn set_person(ref self: ContractState, person: Person) {\n" +#~ " self.person.write(person);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStoringCustomType {\n" +#~ " fn set_person(ref self: TContractState, person: Person);\n" +#~ "}\n" +#~ "\n" +#~ "// Deriving the starknet::Store trait\n" +#~ "// allows us to store the `Person` struct in the contract's storage.\n" +#~ "#[derive(Drop, Serde, Copy, starknet::Store)]\n" +#~ "struct Person {\n" +#~ " age: u8,\n" +#~ " name: felt252\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod StoringCustomType {\n" +#~ " use super::Person;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " person: Person\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StoringCustomType of super::IStoringCustomType {\n" +#~ " fn set_person(ref self: ContractState, person: Person) {\n" +#~ " self.person.write(person);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Custom types in entrypoints" +#~ msgstr "# 入口点中的自定义类型" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISerdeCustomType {\n" +#~ " fn person_input(ref self: TContractState, person: SerdeCustomType::" +#~ "Person);\n" +#~ " fn person_output(self: @TContractState) -> SerdeCustomType::Person;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SerdeCustomType {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " // Deriving the `Serde` trait allows us to use\n" +#~ " // the Person type as an entrypoint parameter and return value\n" +#~ " #[derive(Drop, Serde)]\n" +#~ " struct Person {\n" +#~ " age: u8,\n" +#~ " name: felt252\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SerdeCustomType of super::ISerdeCustomType {\n" +#~ " fn person_input(ref self: ContractState, person: Person) {}\n" +#~ "\n" +#~ " fn person_output(self: @ContractState) -> Person {\n" +#~ " Person { age: 10, name: 'Joe' }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISerdeCustomType {\n" +#~ " fn person_input(ref self: TContractState, person: SerdeCustomType::" +#~ "Person);\n" +#~ " fn person_output(self: @TContractState) -> SerdeCustomType::Person;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SerdeCustomType {\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " // Deriving the `Serde` trait allows us to use\n" +#~ " // the Person type as an entrypoint parameter and return value\n" +#~ " #[derive(Drop, Serde)]\n" +#~ " struct Person {\n" +#~ " age: u8,\n" +#~ " name: felt252\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SerdeCustomType of super::ISerdeCustomType {\n" +#~ " fn person_input(ref self: ContractState, person: Person) {}\n" +#~ "\n" +#~ " fn person_output(self: @ContractState) -> Person {\n" +#~ " Person { age: 10, name: 'Joe' }\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Documentation" +#~ msgstr "# 文档" + +#~ msgid "
Last change: 2023-12-05
" +#~ msgstr "
Last change: 2023-12-05
" + +#~ msgid "# Deploy and interact with contracts" +#~ msgstr "# 部署合约并与合约交互" + +#~ msgid "# Contract interfaces and Traits generation" +#~ msgstr "# 合约接口和Trait生成" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IExplicitInterfaceContract {\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn set_value(ref self: TContractState, value: u32);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ExplicitInterfaceContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ExplicitInterfaceContract of super::" +#~ "IExplicitInterfaceContract {\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IExplicitInterfaceContract {\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn set_value(ref self: TContractState, value: u32);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ExplicitInterfaceContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ExplicitInterfaceContract of super::" +#~ "IExplicitInterfaceContract {\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod ImplicitInterfaceContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(per_item)]\n" +#~ " #[generate_trait]\n" +#~ " impl ImplicitInterfaceContract of IImplicitInterfaceContract {\n" +#~ " #[external(v0)]\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " #[external(v0)]\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod ImplicitInterfaceContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(per_item)]\n" +#~ " #[generate_trait]\n" +#~ " impl ImplicitInterfaceContract of IImplicitInterfaceContract {\n" +#~ " #[external(v0)]\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " #[external(v0)]\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IImplicitInternalContract {\n" +#~ " fn add(ref self: TContractState, nb: u32);\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn get_const(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ImplicitInternalContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl InternalFunctions of InternalFunctionsTrait {\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " fn get_const() -> u32 {\n" +#~ " 42\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState) {\n" +#~ " self.set_value(0);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ImplicitInternalContract of super::" +#~ "IImplicitInternalContract {\n" +#~ " fn add(ref self: ContractState, nb: u32) {\n" +#~ " self.set_value(self.value.read() + nb);\n" +#~ " }\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " fn get_const(self: @ContractState) -> u32 {\n" +#~ " self.get_const()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IImplicitInternalContract {\n" +#~ " fn add(ref self: TContractState, nb: u32);\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn get_const(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ImplicitInternalContract {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl InternalFunctions of InternalFunctionsTrait {\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " fn get_const() -> u32 {\n" +#~ " 42\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState) {\n" +#~ " self.set_value(0);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ImplicitInternalContract of super::" +#~ "IImplicitInternalContract {\n" +#~ " fn add(ref self: ContractState, nb: u32) {\n" +#~ " self.set_value(self.value.read() + nb);\n" +#~ " }\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ " fn get_const(self: @ContractState) -> u32 {\n" +#~ " self.get_const()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-11-26
" +#~ msgstr "
Last change: 2023-11-26
" + +#~ msgid "# Calling other contracts" +#~ msgstr "# 调用其他合约" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ICallee {\n" +#~ " fn set_value(ref self: TContractState, value: u128) -> u128;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod Callee {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ICalleeImpl of super::ICallee {\n" +#~ " fn set_value(ref self: ContractState, value: u128) -> u128 {\n" +#~ " self.value.write(value);\n" +#~ " value\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ICallee {\n" +#~ " fn set_value(ref self: TContractState, value: u128) -> u128;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod Callee {\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u128,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ICalleeImpl of super::ICallee {\n" +#~ " fn set_value(ref self: ContractState, value: u128) -> u128 {\n" +#~ " self.value.write(value);\n" +#~ " value\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "// We need to have the interface of the callee contract defined\n" +#~ "// so that we can import the Dispatcher.\n" +#~ "#[starknet::interface]\n" +#~ "trait ICallee {\n" +#~ " fn set_value(ref self: TContractState, value: u128) -> u128;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICaller {\n" +#~ " fn set_value_from_address(ref self: TContractState, addr: " +#~ "ContractAddress, value: u128);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod Caller {\n" +#~ " // We import the Dispatcher of the called contract\n" +#~ " use super::{ICalleeDispatcher, ICalleeDispatcherTrait};\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ICallerImpl of super::ICaller {\n" +#~ " fn set_value_from_address(ref self: ContractState, addr: " +#~ "ContractAddress, value: u128) {\n" +#~ " ICalleeDispatcher { contract_address: addr }." +#~ "set_value(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "// We need to have the interface of the callee contract defined\n" +#~ "// so that we can import the Dispatcher.\n" +#~ "#[starknet::interface]\n" +#~ "trait ICallee {\n" +#~ " fn set_value(ref self: TContractState, value: u128) -> u128;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICaller {\n" +#~ " fn set_value_from_address(ref self: TContractState, addr: " +#~ "ContractAddress, value: u128);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod Caller {\n" +#~ " // We import the Dispatcher of the called contract\n" +#~ " use super::{ICalleeDispatcher, ICalleeDispatcherTrait};\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ICallerImpl of super::ICaller {\n" +#~ " fn set_value_from_address(ref self: ContractState, addr: " +#~ "ContractAddress, value: u128) {\n" +#~ " ICalleeDispatcher { contract_address: addr }." +#~ "set_value(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::{ContractAddress, ClassHash};\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICounterFactory {\n" +#~ " /// Create a new counter contract from stored arguments\n" +#~ " fn create_counter(ref self: TContractState) -> ContractAddress;\n" +#~ "\n" +#~ " /// Create a new counter contract from the given arguments\n" +#~ " fn create_counter_at(ref self: TContractState, init_value: u128) -> " +#~ "ContractAddress;\n" +#~ "\n" +#~ " /// Update the argument\n" +#~ " fn update_init_value(ref self: TContractState, init_value: u128);\n" +#~ "\n" +#~ " /// Update the class hash of the Counter contract to deploy when " +#~ "creating a new counter\n" +#~ " fn update_counter_class_hash(ref self: TContractState, " +#~ "counter_class_hash: ClassHash);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod CounterFactory {\n" +#~ " use starknet::{ContractAddress, ClassHash};\n" +#~ " use starknet::syscalls::deploy_syscall;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " /// Store the constructor arguments of the contract to deploy\n" +#~ " init_value: u128,\n" +#~ " /// Store the class hash of the contract to deploy\n" +#~ " counter_class_hash: ClassHash,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, init_value: u128, class_hash: " +#~ "ClassHash) {\n" +#~ " self.init_value.write(init_value);\n" +#~ " self.counter_class_hash.write(class_hash);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl Factory of super::ICounterFactory {\n" +#~ " fn create_counter_at(ref self: ContractState, init_value: u128) -" +#~ "> ContractAddress {\n" +#~ " // Contructor arguments\n" +#~ " let mut constructor_calldata: Array:: = array!" +#~ "[init_value.into()];\n" +#~ "\n" +#~ " // Contract deployment\n" +#~ " let (deployed_address, _) = deploy_syscall(\n" +#~ " self.counter_class_hash.read(), 0, constructor_calldata." +#~ "span(), false\n" +#~ " )\n" +#~ " .expect('failed to deploy counter');\n" +#~ "\n" +#~ " deployed_address\n" +#~ " }\n" +#~ "\n" +#~ " fn create_counter(ref self: ContractState) -> ContractAddress {\n" +#~ " self.create_counter_at(self.init_value.read())\n" +#~ " }\n" +#~ "\n" +#~ " fn update_init_value(ref self: ContractState, init_value: u128) " +#~ "{\n" +#~ " self.init_value.write(init_value);\n" +#~ " }\n" +#~ "\n" +#~ " fn update_counter_class_hash(ref self: ContractState, " +#~ "counter_class_hash: ClassHash) {\n" +#~ " self.counter_class_hash.write(counter_class_hash);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::{ContractAddress, ClassHash};\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ICounterFactory {\n" +#~ " /// Create a new counter contract from stored arguments\n" +#~ " fn create_counter(ref self: TContractState) -> ContractAddress;\n" +#~ "\n" +#~ " /// Create a new counter contract from the given arguments\n" +#~ " fn create_counter_at(ref self: TContractState, init_value: u128) -> " +#~ "ContractAddress;\n" +#~ "\n" +#~ " /// Update the argument\n" +#~ " fn update_init_value(ref self: TContractState, init_value: u128);\n" +#~ "\n" +#~ " /// Update the class hash of the Counter contract to deploy when " +#~ "creating a new counter\n" +#~ " fn update_counter_class_hash(ref self: TContractState, " +#~ "counter_class_hash: ClassHash);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod CounterFactory {\n" +#~ " use starknet::{ContractAddress, ClassHash};\n" +#~ " use starknet::syscalls::deploy_syscall;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " /// Store the constructor arguments of the contract to deploy\n" +#~ " init_value: u128,\n" +#~ " /// Store the class hash of the contract to deploy\n" +#~ " counter_class_hash: ClassHash,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, init_value: u128, class_hash: " +#~ "ClassHash) {\n" +#~ " self.init_value.write(init_value);\n" +#~ " self.counter_class_hash.write(class_hash);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl Factory of super::ICounterFactory {\n" +#~ " fn create_counter_at(ref self: ContractState, init_value: u128) -" +#~ "> ContractAddress {\n" +#~ " // Contructor arguments\n" +#~ " let mut constructor_calldata: Array:: = array!" +#~ "[init_value.into()];\n" +#~ "\n" +#~ " // Contract deployment\n" +#~ " let (deployed_address, _) = deploy_syscall(\n" +#~ " self.counter_class_hash.read(), 0, constructor_calldata." +#~ "span(), false\n" +#~ " )\n" +#~ " .expect('failed to deploy counter');\n" +#~ "\n" +#~ " deployed_address\n" +#~ " }\n" +#~ "\n" +#~ " fn create_counter(ref self: ContractState) -> ContractAddress {\n" +#~ " self.create_counter_at(self.init_value.read())\n" +#~ " }\n" +#~ "\n" +#~ " fn update_init_value(ref self: ContractState, init_value: u128) " +#~ "{\n" +#~ " self.init_value.write(init_value);\n" +#~ " }\n" +#~ "\n" +#~ " fn update_counter_class_hash(ref self: ContractState, " +#~ "counter_class_hash: ClassHash) {\n" +#~ " self.counter_class_hash.write(counter_class_hash);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "" +#~ msgstr "" +#~ "" + +#~ msgid "" +#~ "\n" +#~ "\n" +#~ "
Last change: 2023-10-19
" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "
Last change: 2023-10-19
" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleContract {\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn get_owner(self: @TContractState) -> ContractAddress;\n" +#~ " fn set_value(ref self: TContractState, value: u32);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleContract {\n" +#~ " use starknet::{get_caller_address, ContractAddress};\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32,\n" +#~ " owner: ContractAddress\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, initial_value: u32) {\n" +#~ " self.value.write(initial_value);\n" +#~ " self.owner.write(get_caller_address());\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleContract of super::ISimpleContract {\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_owner(self: @ContractState) -> ContractAddress {\n" +#~ " self.owner.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " assert(self.owner.read() == get_caller_address(), 'Not " +#~ "owner');\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleContract {\n" +#~ " fn get_value(self: @TContractState) -> u32;\n" +#~ " fn get_owner(self: @TContractState) -> ContractAddress;\n" +#~ " fn set_value(ref self: TContractState, value: u32);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleContract {\n" +#~ " use starknet::{get_caller_address, ContractAddress};\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " value: u32,\n" +#~ " owner: ContractAddress\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, initial_value: u32) {\n" +#~ " self.value.write(initial_value);\n" +#~ " self.owner.write(get_caller_address());\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleContract of super::ISimpleContract {\n" +#~ " fn get_value(self: @ContractState) -> u32 {\n" +#~ " self.value.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_owner(self: @ContractState) -> ContractAddress {\n" +#~ " self.owner.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn set_value(ref self: ContractState, value: u32) {\n" +#~ " assert(self.owner.read() == get_caller_address(), ‘Not " +#~ "owner’);\n" +#~ " self.value.write(value);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[cfg(test)]\n" +#~ "mod tests {\n" +#~ " // Import the interface and dispatcher to be able to interact with " +#~ "the contract.\n" +#~ " use sbe_testing::contract::{\n" +#~ " ISimpleContract, SimpleContract, ISimpleContractDispatcher, " +#~ "ISimpleContractDispatcherTrait\n" +#~ " };\n" +#~ "\n" +#~ " // Import the deploy syscall to be able to deploy the contract.\n" +#~ " use starknet::class_hash::Felt252TryIntoClassHash;\n" +#~ " use starknet::{\n" +#~ " deploy_syscall, ContractAddress, get_caller_address, " +#~ "get_contract_address,\n" +#~ " contract_address_const\n" +#~ " };\n" +#~ "\n" +#~ " // Use starknet test utils to fake the transaction context.\n" +#~ " use starknet::testing::{set_caller_address, set_contract_address};\n" +#~ "\n" +#~ " // Deploy the contract and return its dispatcher.\n" +#~ " fn deploy(initial_value: u32) -> ISimpleContractDispatcher {\n" +#~ " // Set up constructor arguments.\n" +#~ " let mut calldata = ArrayTrait::new();\n" +#~ " initial_value.serialize(ref calldata);\n" +#~ "\n" +#~ " // Declare and deploy\n" +#~ " let (contract_address, _) = deploy_syscall(\n" +#~ " SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, " +#~ "calldata.span(), false\n" +#~ " )\n" +#~ " .unwrap();\n" +#~ "\n" +#~ " // Return the dispatcher.\n" +#~ " // The dispatcher allows to interact with the contract based on " +#~ "its interface.\n" +#~ " ISimpleContractDispatcher { contract_address }\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_deploy() {\n" +#~ " let initial_value: u32 = 10;\n" +#~ " let contract = deploy(initial_value);\n" +#~ "\n" +#~ " assert(contract.get_value() == initial_value, 'wrong initial " +#~ "value');\n" +#~ " assert(contract.get_owner() == get_contract_address(), 'wrong " +#~ "owner');\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_set_as_owner() {\n" +#~ " // Fake the caller address to address 1\n" +#~ " let owner = contract_address_const::<1>();\n" +#~ " set_contract_address(owner);\n" +#~ "\n" +#~ " let contract = deploy(10);\n" +#~ " assert(contract.get_owner() == owner, 'wrong owner');\n" +#~ "\n" +#~ " // Fake the contract address to address 1\n" +#~ " set_contract_address(owner);\n" +#~ " let new_value: u32 = 20;\n" +#~ " contract.set_value(new_value);\n" +#~ "\n" +#~ " assert(contract.get_value() == new_value, 'wrong value');\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[should_panic]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_set_not_owner() {\n" +#~ " let owner = contract_address_const::<1>();\n" +#~ " set_contract_address(owner);\n" +#~ "\n" +#~ " let contract = deploy(10);\n" +#~ "\n" +#~ " let not_owner = contract_address_const::<2>();\n" +#~ " set_contract_address(not_owner);\n" +#~ "\n" +#~ " let new_value: u32 = 20;\n" +#~ " contract.set_value(new_value);\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[cfg(test)]\n" +#~ "mod tests {\n" +#~ " // 导入接口和调度器,以便能够与合约进行交互\n" +#~ " use sbe_testing::contract::{\n" +#~ " ISimpleContract, SimpleContract, ISimpleContractDispatcher, " +#~ "ISimpleContractDispatcherTrait\n" +#~ " };\n" +#~ "\n" +#~ " //导入部署 deploy_syscall,以便能够部署合约\n" +#~ " use starknet::class_hash::Felt252TryIntoClassHash;\n" +#~ " use starknet::{\n" +#~ " deploy_syscall, ContractAddress, get_caller_address, " +#~ "get_contract_address,\n" +#~ " contract_address_const\n" +#~ " };\n" +#~ "\n" +#~ " // 使用 starknet 测试工具来模拟上下文交易\n" +#~ " use starknet::testing::{set_caller_address, set_contract_address};\n" +#~ "\n" +#~ " // 部署合约并返回其调度器\n" +#~ " fn deploy(initial_value: u32) -> ISimpleContractDispatcher {\n" +#~ " // Set up constructor arguments.\n" +#~ " let mut calldata = ArrayTrait::new();\n" +#~ " initial_value.serialize(ref calldata);\n" +#~ "\n" +#~ " // 声明并部署合约\n" +#~ " let (contract_address, _) = deploy_syscall(\n" +#~ " SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, " +#~ "calldata.span(), false\n" +#~ " )\n" +#~ " .unwrap();\n" +#~ "\n" +#~ " // 返回调度器\n" +#~ " // 调度器允许根据合约的接口与其进行交互\n" +#~ " ISimpleContractDispatcher { contract_address }\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_deploy() {\n" +#~ " let initial_value: u32 = 10;\n" +#~ " let contract = deploy(initial_value);\n" +#~ "\n" +#~ " assert(contract.get_value() == initial_value, ‘wrong initial " +#~ "value’);\n" +#~ " assert(contract.get_owner() == get_contract_address(), ‘wrong " +#~ "owner’);\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_set_as_owner() {\n" +#~ " // 将调用者地址设置为地址1\n" +#~ " let owner = contract_address_const::<1>();\n" +#~ " set_contract_address(owner);\n" +#~ "\n" +#~ " let contract = deploy(10);\n" +#~ " assert(contract.get_owner() == owner, ‘wrong owner’);\n" +#~ "\n" +#~ " // 将合约地址设置为地址1\n" +#~ " set_contract_address(owner);\n" +#~ " let new_value: u32 = 20;\n" +#~ " contract.set_value(new_value);\n" +#~ "\n" +#~ " assert(contract.get_value() == new_value, ‘wrong value’);\n" +#~ " }\n" +#~ "\n" +#~ " #[test]\n" +#~ " #[should_panic]\n" +#~ " #[available_gas(2000000000)]\n" +#~ " fn test_set_not_owner() {\n" +#~ " let owner = contract_address_const::<1>();\n" +#~ " set_contract_address(owner);\n" +#~ "\n" +#~ " let contract = deploy(10);\n" +#~ "\n" +#~ " let not_owner = contract_address_const::<2>();\n" +#~ " set_contract_address(not_owner);\n" +#~ "\n" +#~ " let new_value: u32 = 20;\n" +#~ " contract.set_value(new_value);\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "- `set_caller_address(address: ContractAddress)`\n" +#~ "- `set_contract_address(address: ContractAddress)`\n" +#~ "- `set_block_number(block_number: u64)`\n" +#~ "- `set_block_timestamp(block_timestamp: u64)`\n" +#~ "- `set_account_contract_address(address: ContractAddress)`\n" +#~ "- `set_max_fee(fee: u128)`" +#~ msgstr "" +#~ "- `set_caller_address(address: ContractAddress)`\n" +#~ "- `set_contract_address(address: ContractAddress)`\n" +#~ "- `set_block_number(block_number: u64)`\n" +#~ "- `set_block_timestamp(block_timestamp: u64)`\n" +#~ "- `set_account_contract_address(address: ContractAddress)`\n" +#~ "- `set_max_fee(fee: u128)`" + +#~ msgid "" +#~ "- `get_caller_address() -> ContractAddress`\n" +#~ "- `get_contract_address() -> ContractAddress`\n" +#~ "- `get_block_info() -> Box`\n" +#~ "- `get_tx_info() -> Box`\n" +#~ "- `get_block_timestamp() -> u64`\n" +#~ "- `get_block_number() -> u64`" +#~ msgstr "" +#~ "- `get_caller_address() -> ContractAddress`\n" +#~ "- `get_contract_address() -> ContractAddress`\n" +#~ "- `get_block_info() -> Box`\n" +#~ "- `get_tx_info() -> Box`\n" +#~ "- `get_block_timestamp() -> u64`\n" +#~ "- `get_block_number() -> u64`" + +#~ msgid "" +#~ msgstr "" + +#~ msgid "
Last change: 2023-10-31
" +#~ msgstr "
Last change: 2023-10-31
" + +#~ msgid "" +#~ "```rust\n" +#~ " let felt: felt252 = 100;\n" +#~ " let felt_as_str = 'Hello Starknet!';\n" +#~ "\n" +#~ " let felt = felt + felt_as_str;\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ " let felt: felt252 = 100;\n" +#~ " let felt_as_str = ‘Hello Starknet!’;\n" +#~ "\n" +#~ " let felt = felt + felt_as_str;\n" +#~ "```" + +#~ msgid "# Mapping" +#~ msgstr "# Mapping" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IMappingExample {\n" +#~ " fn register_user(ref self: TContractState, student_add: " +#~ "ContractAddress, studentName: felt252);\n" +#~ " fn record_student_score(\n" +#~ " ref self: TContractState, student_add: ContractAddress, subject: " +#~ "felt252, score: u16\n" +#~ " );\n" +#~ " fn view_student_name(self: @TContractState, student_add: " +#~ "ContractAddress) -> felt252;\n" +#~ " fn view_student_score(\n" +#~ " self: @TContractState, student_add: ContractAddress, subject: " +#~ "felt252\n" +#~ " ) -> u16;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod MappingContract {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " students_name: LegacyMap::,\n" +#~ " students_result_record: LegacyMap::<(ContractAddress, felt252), " +#~ "u16>,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl External of super::IMappingExample {\n" +#~ " fn register_user(\n" +#~ " ref self: ContractState, student_add: ContractAddress, " +#~ "studentName: felt252\n" +#~ " ) {\n" +#~ " self.students_name.write(student_add, studentName);\n" +#~ " }\n" +#~ "\n" +#~ " fn record_student_score(\n" +#~ " ref self: ContractState, student_add: ContractAddress, " +#~ "subject: felt252, score: u16\n" +#~ " ) {\n" +#~ " self.students_result_record.write((student_add, subject), " +#~ "score);\n" +#~ " }\n" +#~ "\n" +#~ " fn view_student_name(self: @ContractState, student_add: " +#~ "ContractAddress) -> felt252 {\n" +#~ " self.students_name.read(student_add)\n" +#~ " }\n" +#~ "\n" +#~ " fn view_student_score(\n" +#~ " self: @ContractState, student_add: ContractAddress, subject: " +#~ "felt252\n" +#~ " ) -> u16 {\n" +#~ " // for a 2D mapping its important to take note of the amount " +#~ "of brackets being used.\n" +#~ " self.students_result_record.read((student_add, subject))\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IMappingExample {\n" +#~ " fn register_user(ref self: TContractState, student_add: " +#~ "ContractAddress, studentName: felt252);\n" +#~ " fn record_student_score(\n" +#~ " ref self: TContractState, student_add: ContractAddress, subject: " +#~ "felt252, score: u16\n" +#~ " );\n" +#~ " fn view_student_name(self: @TContractState, student_add: " +#~ "ContractAddress) -> felt252;\n" +#~ " fn view_student_score(\n" +#~ " self: @TContractState, student_add: ContractAddress, subject: " +#~ "felt252\n" +#~ " ) -> u16;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod MappingContract {\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " students_name: LegacyMap::,\n" +#~ " students_result_record: LegacyMap::<(ContractAddress, felt252), " +#~ "u16>,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl External of super::IMappingExample {\n" +#~ " fn register_user(\n" +#~ " ref self: ContractState, student_add: ContractAddress, " +#~ "studentName: felt252\n" +#~ " ) {\n" +#~ " self.students_name.write(student_add, studentName);\n" +#~ " }\n" +#~ "\n" +#~ " fn record_student_score(\n" +#~ " ref self: ContractState, student_add: ContractAddress, " +#~ "subject: felt252, score: u16\n" +#~ " ) {\n" +#~ " self.students_result_record.write((student_add, subject), " +#~ "score);\n" +#~ " }\n" +#~ "\n" +#~ " fn view_student_name(self: @ContractState, student_add: " +#~ "ContractAddress) -> felt252 {\n" +#~ " self.students_name.read(student_add)\n" +#~ " }\n" +#~ "\n" +#~ " fn view_student_score(\n" +#~ " self: @ContractState, student_add: ContractAddress, subject: " +#~ "felt252\n" +#~ " ) -> u16 {\n" +#~ " // 对于二维映射,重要的是注意使用的括号数量。\n" +#~ " self.students_result_record.read((student_add, subject))\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Arrays" +#~ msgstr "# 数组" + +#~ msgid "" +#~ "```rust\n" +#~ "trait ArrayTrait {\n" +#~ " fn new() -> Array;\n" +#~ " fn append(ref self: Array, value: T);\n" +#~ " fn pop_front(ref self: Array) -> Option nopanic;\n" +#~ " fn pop_front_consume(self: Array) -> Option<(Array, T)> " +#~ "nopanic;\n" +#~ " fn get(self: @Array, index: usize) -> Option>;\n" +#~ " fn at(self: @Array, index: usize) -> @T;\n" +#~ " fn len(self: @Array) -> usize;\n" +#~ " fn is_empty(self: @Array) -> bool;\n" +#~ " fn span(self: @Array) -> Span;\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "trait ArrayTrait {\n" +#~ " fn new() -> Array;\n" +#~ " fn append(ref self: Array, value: T);\n" +#~ " fn pop_front(ref self: Array) -> Option nopanic;\n" +#~ " fn pop_front_consume(self: Array) -> Option<(Array, T)> " +#~ "nopanic;\n" +#~ " fn get(self: @Array, index: usize) -> Option>;\n" +#~ " fn at(self: @Array, index: usize) -> @T;\n" +#~ " fn len(self: @Array) -> usize;\n" +#~ " fn is_empty(self: @Array) -> bool;\n" +#~ " fn span(self: @Array) -> Span;\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "fn array() -> bool {\n" +#~ " let mut arr = ArrayTrait::::new();\n" +#~ " arr.append(10);\n" +#~ " arr.append(20);\n" +#~ " arr.append(30);\n" +#~ "\n" +#~ " assert(arr.len() == 3, 'array length should be 3');\n" +#~ "\n" +#~ " let first_value = arr.pop_front().unwrap();\n" +#~ " assert(first_value == 10, 'first value should match');\n" +#~ "\n" +#~ " let second_value = *arr.at(0);\n" +#~ " assert(second_value == 20, 'second value should match');\n" +#~ "\n" +#~ " // Returns true if an array is empty, then false if it isn't.\n" +#~ " arr.is_empty()\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "fn array() -> bool {\n" +#~ " let mut arr = ArrayTrait::::new();\n" +#~ " arr.append(10);\n" +#~ " arr.append(20);\n" +#~ " arr.append(30);\n" +#~ "\n" +#~ " assert(arr.len() == 3, ‘array length should be 3’);\n" +#~ "\n" +#~ " let first_value = arr.pop_front().unwrap();\n" +#~ " assert(first_value == 10, ‘first value should match’);\n" +#~ "\n" +#~ " let second_value = *arr.at(0);\n" +#~ " assert(second_value == 20, ‘second value should match’);\n" +#~ "\n" +#~ " // 如果数组为空,返回 true;如果不为空,返回 false。\n" +#~ " arr.is_empty()\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Loop" +#~ msgstr "# 循环" + +#~ msgid "" +#~ "```rust\n" +#~ " let mut arr = ArrayTrait::new();\n" +#~ "\n" +#~ " // Same as ~ while (i < 10) arr.append(i++);\n" +#~ " let mut i: u32 = 0;\n" +#~ " let limit = 10;\n" +#~ " loop {\n" +#~ " if i == limit {\n" +#~ " break;\n" +#~ " };\n" +#~ "\n" +#~ " arr.append(i);\n" +#~ "\n" +#~ " i += 1;\n" +#~ " };\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ " let mut arr = ArrayTrait::new();\n" +#~ "\n" +#~ " // 与 ~ while (i < 10) arr.append(i++); 相同\n" +#~ " let mut i: u32 = 0;\n" +#~ " let limit = 10;\n" +#~ " loop {\n" +#~ " if i == limit {\n" +#~ " break;\n" +#~ " };\n" +#~ "\n" +#~ " arr.append(i);\n" +#~ "\n" +#~ " i += 1;\n" +#~ " };\n" +#~ "```" + +#~ msgid "# Match" +#~ msgstr "# 分支" + +#~ msgid "" +#~ "```rust\n" +#~ "#[derive(Drop, Serde)]\n" +#~ "enum Colour {\n" +#~ " Red,\n" +#~ " Blue,\n" +#~ " Green,\n" +#~ " Orange,\n" +#~ " Black\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Drop, Serde)]\n" +#~ "enum Coin {\n" +#~ " Penny,\n" +#~ " Nickel,\n" +#~ " Dime,\n" +#~ " Quarter,\n" +#~ "}\n" +#~ "\n" +#~ "fn value_in_cents(coin: Coin) -> felt252 {\n" +#~ " match coin {\n" +#~ " Coin::Penny => 1,\n" +#~ " Coin::Nickel => 5,\n" +#~ " Coin::Dime => 10,\n" +#~ " Coin::Quarter => 25,\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "fn specified_colour(colour: Colour) -> felt252 {\n" +#~ " let mut response: felt252 = '';\n" +#~ "\n" +#~ " match colour {\n" +#~ " Colour::Red => { response = 'You passed in Red'; },\n" +#~ " Colour::Blue => { response = 'You passed in Blue'; },\n" +#~ " Colour::Green => { response = 'You passed in Green'; },\n" +#~ " Colour::Orange => { response = 'You passed in Orange'; },\n" +#~ " Colour::Black => { response = 'You passed in Black'; },\n" +#~ " };\n" +#~ "\n" +#~ " response\n" +#~ "}\n" +#~ "\n" +#~ "fn quiz(num: felt252) -> felt252 {\n" +#~ " let mut response: felt252 = '';\n" +#~ "\n" +#~ " match num {\n" +#~ " 0 => { response = 'You failed' },\n" +#~ " _ => { response = 'You Passed' },\n" +#~ " };\n" +#~ "\n" +#~ " response\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[derive(Drop, Serde)]\n" +#~ "enum Colour {\n" +#~ " Red,\n" +#~ " Blue,\n" +#~ " Green,\n" +#~ " Orange,\n" +#~ " Black\n" +#~ "}\n" +#~ "\n" +#~ "#[derive(Drop, Serde)]\n" +#~ "enum Coin {\n" +#~ " Penny,\n" +#~ " Nickel,\n" +#~ " Dime,\n" +#~ " Quarter,\n" +#~ "}\n" +#~ "\n" +#~ "fn value_in_cents(coin: Coin) -> felt252 {\n" +#~ " match coin {\n" +#~ " Coin::Penny => 1,\n" +#~ " Coin::Nickel => 5,\n" +#~ " Coin::Dime => 10,\n" +#~ " Coin::Quarter => 25,\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "fn specified_colour(colour: Colour) -> felt252 {\n" +#~ " let mut response: felt252 = ‘’;\n" +#~ "\n" +#~ " match colour {\n" +#~ " Colour::Red => { response = ‘You passed in Red’; },\n" +#~ " Colour::Blue => { response = ‘You passed in Blue’; },\n" +#~ " Colour::Green => { response = ‘You passed in Green’; },\n" +#~ " Colour::Orange => { response = ‘You passed in Orange’; },\n" +#~ " Colour::Black => { response = ‘You passed in Black’; },\n" +#~ " };\n" +#~ "\n" +#~ " response\n" +#~ "}\n" +#~ "\n" +#~ "fn quiz(num: felt252) -> felt252 {\n" +#~ " let mut response: felt252 = ‘’;\n" +#~ "\n" +#~ " match num {\n" +#~ " 0 => { response = ‘You failed’ },\n" +#~ " _ => { response = ‘You Passed’ },\n" +#~ " };\n" +#~ "\n" +#~ " response\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Tuples" +#~ msgstr "# 元组" + +#~ msgid "" +#~ "```rust\n" +#~ " let address = \"0x000\";\n" +#~ " let age = 20;\n" +#~ " let active = true;\n" +#~ "\n" +#~ " // Create tuple\n" +#~ " let user_tuple = (address, age, active);\n" +#~ "\n" +#~ " // Access tuple\n" +#~ " let (address, age, active) = stored_tuple;\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ " let address = “0x000”;\n" +#~ " let age = 20;\n" +#~ " let active = true;\n" +#~ "\n" +#~ " // Create tuple\n" +#~ " let user_tuple = (address, age, active);\n" +#~ "\n" +#~ " // Access tuple\n" +#~ " let (address, age, active) = stored_tuple;\n" +#~ "```" + +#~ msgid "# Struct" +#~ msgstr "# 结构体" + +#~ msgid "" +#~ "```rust\n" +#~ "// With Store, you can store Data's structs in the storage part of " +#~ "contracts.\n" +#~ "#[derive(Drop, starknet::Store)]\n" +#~ "struct Data {\n" +#~ " address: starknet::ContractAddress,\n" +#~ " age: u8\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "// 使用 Store,您可以将 Data 结构体存储在合约的存储部分。\n" +#~ "#[derive(Drop, starknet::Store)]\n" +#~ "struct Data {\n" +#~ " address: starknet::ContractAddress,\n" +#~ " age: u8\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Type casting" +#~ msgstr "# 类型转换" + +#~ msgid "" +#~ "```rust\n" +#~ " let a_number: u32 = 15;\n" +#~ " let my_felt252 = 15;\n" +#~ "\n" +#~ " // Since a u32 might not fit in a u8 and a u16, we need to use " +#~ "try_into,\n" +#~ " // then unwrap the Option type thats returned.\n" +#~ " let new_u8: u8 = a_number.try_into().unwrap();\n" +#~ " let new_u16: u16 = a_number.try_into().unwrap();\n" +#~ "\n" +#~ " // since new_u32 is the of the same type (u32) as rand_number, we can " +#~ "directly assign them,\n" +#~ " // or use the .into() method.\n" +#~ " let new_u32: u32 = a_number;\n" +#~ "\n" +#~ " // When typecasting from a smaller size to an equal or larger size we " +#~ "use the .into() method.\n" +#~ " // Note: u64 and u128 are larger than u32, so a u32 type will always " +#~ "fit into them.\n" +#~ " let new_u64: u64 = a_number.into();\n" +#~ " let new_u128: u128 = a_number.into();\n" +#~ "\n" +#~ " // Since a felt252 is smaller than a u256, we can use the into() " +#~ "method\n" +#~ " let new_u256: u256 = my_felt252.into();\n" +#~ " let new_felt252: felt252 = new_u16.into();\n" +#~ "\n" +#~ " //note a usize is smaller than a felt so we use the try_into\n" +#~ " let new_usize: usize = my_felt252.try_into().unwrap();\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ " let a_number: u32 = 15;\n" +#~ " let my_felt252 = 15;\n" +#~ "\n" +#~ " // 由于 u32 可能不匹配 u8 和 u16,我们需要使用 try_into\n" +#~ " // 然后解包返回的 Option 类型。\n" +#~ " let new_u8: u8 = a_number.try_into().unwrap();\n" +#~ " let new_u16: u16 = a_number.try_into().unwrap();\n" +#~ "\n" +#~ " // 由于 new_u32 的类型(u32)与 a_number 相同,我们可以直接赋值\n" +#~ " // 或使用 .into() 方法\n" +#~ " let new_u32: u32 = a_number;\n" +#~ "\n" +#~ " // 当从较小的大小类型强制转换为相等或较大的大小类型时,我们使用 ." +#~ "into() 方法\n" +#~ " // 注意:u64 和 u128 大于 u32,所以 u32 类型将始终适合其中\n" +#~ " let new_u64: u64 = a_number.into();\n" +#~ " let new_u128: u128 = a_number.into();\n" +#~ "\n" +#~ " // 由于 felt252 比 u256 小,我们可以使用 into() 方法\n" +#~ " let new_u256: u256 = my_felt252.into();\n" +#~ " let new_felt252: felt252 = new_u16.into();\n" +#~ "\n" +#~ " //注意,usize 比 felt252 小,因此我们使用 try_into\n" +#~ " let new_usize: usize = my_felt252.try_into().unwrap();\n" +#~ "```" + +#~ msgid "# Upgradeable Contract" +#~ msgstr "# 可升级合约" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::class_hash::ClassHash;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IUpgradeableContract {\n" +#~ " fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" +#~ " fn version(self: @TContractState) -> u8;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod UpgradeableContract_V0 {\n" +#~ " use starknet::class_hash::ClassHash;\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Upgraded: Upgraded\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Upgraded {\n" +#~ " implementation: ClassHash\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl UpgradeableContract of super::" +#~ "IUpgradeableContract {\n" +#~ " fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" +#~ " assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" +#~ " starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" +#~ " self.emit(Event::Upgraded(Upgraded { implementation: " +#~ "impl_hash }))\n" +#~ " }\n" +#~ "\n" +#~ " fn version(self: @ContractState) -> u8 {\n" +#~ " 0\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::class_hash::ClassHash;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IUpgradeableContract {\n" +#~ " fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" +#~ " fn version(self: @TContractState) -> u8;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod UpgradeableContract_V0 {\n" +#~ " use starknet::class_hash::ClassHash;\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Upgraded: Upgraded\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Upgraded {\n" +#~ " implementation: ClassHash\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl UpgradeableContract of super::" +#~ "IUpgradeableContract {\n" +#~ " fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" +#~ " assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" +#~ " starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" +#~ " self.emit(Event::Upgraded(Upgraded { implementation: " +#~ "impl_hash }))\n" +#~ " }\n" +#~ "\n" +#~ " fn version(self: @ContractState) -> u8 {\n" +#~ " 0\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::class_hash::ClassHash;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IUpgradeableContract {\n" +#~ " fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" +#~ " fn version(self: @TContractState) -> u8;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod UpgradeableContract_V1 {\n" +#~ " use starknet::class_hash::ClassHash;\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Upgraded: Upgraded\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Upgraded {\n" +#~ " implementation: ClassHash\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl UpgradeableContract of super::" +#~ "IUpgradeableContract {\n" +#~ " fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" +#~ " assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" +#~ " starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" +#~ " self.emit(Event::Upgraded(Upgraded { implementation: " +#~ "impl_hash }))\n" +#~ " }\n" +#~ "\n" +#~ " fn version(self: @ContractState) -> u8 {\n" +#~ " 1\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::class_hash::ClassHash;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IUpgradeableContract {\n" +#~ " fn upgrade(ref self: TContractState, impl_hash: ClassHash);\n" +#~ " fn version(self: @TContractState) -> u8;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod UpgradeableContract_V1 {\n" +#~ " use starknet::class_hash::ClassHash;\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Upgraded: Upgraded\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Upgraded {\n" +#~ " implementation: ClassHash\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl UpgradeableContract of super::" +#~ "IUpgradeableContract {\n" +#~ " fn upgrade(ref self: ContractState, impl_hash: ClassHash) {\n" +#~ " assert(!impl_hash.is_zero(), 'Class hash cannot be zero');\n" +#~ " starknet::replace_class_syscall(impl_hash).unwrap_syscall();\n" +#~ " self.emit(Event::Upgraded(Upgraded { implementation: " +#~ "impl_hash }))\n" +#~ " }\n" +#~ "\n" +#~ " fn version(self: @ContractState) -> u8 {\n" +#~ " 1\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::{ContractAddress};\n" +#~ "\n" +#~ "// In order to make contract calls within our Vault,\n" +#~ "// we need to have the interface of the remote ERC20 contract defined to " +#~ "import the Dispatcher.\n" +#~ "#[starknet::interface]\n" +#~ "trait IERC20 {\n" +#~ " fn name(self: @TContractState) -> felt252;\n" +#~ " fn symbol(self: @TContractState) -> felt252;\n" +#~ " fn decimals(self: @TContractState) -> u8;\n" +#~ " fn total_supply(self: @TContractState) -> u256;\n" +#~ " fn balance_of(self: @TContractState, account: ContractAddress) -> " +#~ "u256;\n" +#~ " fn allowance(self: @TContractState, owner: ContractAddress, spender: " +#~ "ContractAddress) -> u256;\n" +#~ " fn transfer(ref self: TContractState, recipient: ContractAddress, " +#~ "amount: u256) -> bool;\n" +#~ " fn transfer_from(\n" +#~ " ref self: TContractState, sender: ContractAddress, recipient: " +#~ "ContractAddress, amount: u256\n" +#~ " ) -> bool;\n" +#~ " fn approve(ref self: TContractState, spender: ContractAddress, " +#~ "amount: u256) -> bool;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleVault {\n" +#~ " fn deposit(ref self: TContractState, amount: u256);\n" +#~ " fn withdraw(ref self: TContractState, shares: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleVault {\n" +#~ " use super::{IERC20Dispatcher, IERC20DispatcherTrait};\n" +#~ " use starknet::{ContractAddress, get_caller_address, " +#~ "get_contract_address};\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " token: IERC20Dispatcher,\n" +#~ " total_supply: u256,\n" +#~ " balance_of: LegacyMap\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, token: ContractAddress) {\n" +#~ " self.token.write(IERC20Dispatcher { contract_address: token });\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " fn _mint(ref self: ContractState, to: ContractAddress, shares: " +#~ "u256) {\n" +#~ " self.total_supply.write(self.total_supply.read() + shares);\n" +#~ " self.balance_of.write(to, self.balance_of.read(to) + " +#~ "shares);\n" +#~ " }\n" +#~ "\n" +#~ " fn _burn(ref self: ContractState, from: ContractAddress, shares: " +#~ "u256) {\n" +#~ " self.total_supply.write(self.total_supply.read() - shares);\n" +#~ " self.balance_of.write(from, self.balance_of.read(from) - " +#~ "shares);\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleVault of super::ISimpleVault {\n" +#~ " fn deposit(ref self: ContractState, amount: u256) {\n" +#~ " // a = amount\n" +#~ " // B = balance of token before deposit\n" +#~ " // T = total supply\n" +#~ " // s = shares to mint\n" +#~ " //\n" +#~ " // (T + s) / T = (a + B) / B \n" +#~ " //\n" +#~ " // s = aT / B\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ "\n" +#~ " let mut shares = 0;\n" +#~ " if self.total_supply.read() == 0 {\n" +#~ " shares = amount;\n" +#~ " } else {\n" +#~ " let balance = self.token.read().balance_of(this);\n" +#~ " shares = (amount * self.total_supply.read()) / balance;\n" +#~ " }\n" +#~ "\n" +#~ " PrivateFunctions::_mint(ref self, caller, shares);\n" +#~ " self.token.read().transfer_from(caller, this, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn withdraw(ref self: ContractState, shares: u256) {\n" +#~ " // a = amount\n" +#~ " // B = balance of token before withdraw\n" +#~ " // T = total supply\n" +#~ " // s = shares to burn\n" +#~ " //\n" +#~ " // (T - s) / T = (B - a) / B \n" +#~ " //\n" +#~ " // a = sB / T\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ "\n" +#~ " let balance = self.token.read().balance_of(this);\n" +#~ " let amount = (shares * balance) / self.total_supply.read();\n" +#~ " PrivateFunctions::_burn(ref self, caller, shares);\n" +#~ " self.token.read().transfer(caller, amount);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::{ContractAddress};\n" +#~ "\n" +#~ "// In order to make contract calls within our Vault,\n" +#~ "// we need to have the interface of the remote ERC20 contract defined to " +#~ "import the Dispatcher.\n" +#~ "#[starknet::interface]\n" +#~ "trait IERC20 {\n" +#~ " fn name(self: @TContractState) -> felt252;\n" +#~ " fn symbol(self: @TContractState) -> felt252;\n" +#~ " fn decimals(self: @TContractState) -> u8;\n" +#~ " fn total_supply(self: @TContractState) -> u256;\n" +#~ " fn balance_of(self: @TContractState, account: ContractAddress) -> " +#~ "u256;\n" +#~ " fn allowance(self: @TContractState, owner: ContractAddress, spender: " +#~ "ContractAddress) -> u256;\n" +#~ " fn transfer(ref self: TContractState, recipient: ContractAddress, " +#~ "amount: u256) -> bool;\n" +#~ " fn transfer_from(\n" +#~ " ref self: TContractState, sender: ContractAddress, recipient: " +#~ "ContractAddress, amount: u256\n" +#~ " ) -> bool;\n" +#~ " fn approve(ref self: TContractState, spender: ContractAddress, " +#~ "amount: u256) -> bool;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait ISimpleVault {\n" +#~ " fn deposit(ref self: TContractState, amount: u256);\n" +#~ " fn withdraw(ref self: TContractState, shares: u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SimpleVault {\n" +#~ " use super::{IERC20Dispatcher, IERC20DispatcherTrait};\n" +#~ " use starknet::{ContractAddress, get_caller_address, " +#~ "get_contract_address};\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " token: IERC20Dispatcher,\n" +#~ " total_supply: u256,\n" +#~ " balance_of: LegacyMap\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(ref self: ContractState, token: ContractAddress) {\n" +#~ " self.token.write(IERC20Dispatcher { contract_address: token });\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " fn _mint(ref self: ContractState, to: ContractAddress, shares: " +#~ "u256) {\n" +#~ " self.total_supply.write(self.total_supply.read() + shares);\n" +#~ " self.balance_of.write(to, self.balance_of.read(to) + " +#~ "shares);\n" +#~ " }\n" +#~ "\n" +#~ " fn _burn(ref self: ContractState, from: ContractAddress, shares: " +#~ "u256) {\n" +#~ " self.total_supply.write(self.total_supply.read() - shares);\n" +#~ " self.balance_of.write(from, self.balance_of.read(from) - " +#~ "shares);\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SimpleVault of super::ISimpleVault {\n" +#~ " fn deposit(ref self: ContractState, amount: u256) {\n" +#~ " // a = amount\n" +#~ " // B = balance of token before deposit\n" +#~ " // T = total supply\n" +#~ " // s = shares to mint\n" +#~ " //\n" +#~ " // (T + s) / T = (a + B) / B \n" +#~ " //\n" +#~ " // s = aT / B\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ "\n" +#~ " let mut shares = 0;\n" +#~ " if self.total_supply.read() == 0 {\n" +#~ " shares = amount;\n" +#~ " } else {\n" +#~ " let balance = self.token.read().balance_of(this);\n" +#~ " shares = (amount * self.total_supply.read()) / balance;\n" +#~ " }\n" +#~ "\n" +#~ " PrivateFunctions::_mint(ref self, caller, shares);\n" +#~ " self.token.read().transfer_from(caller, this, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn withdraw(ref self: ContractState, shares: u256) {\n" +#~ " // a = amount\n" +#~ " // B = balance of token before withdraw\n" +#~ " // T = total supply\n" +#~ " // s = shares to burn\n" +#~ " //\n" +#~ " // (T - s) / T = (B - a) / B \n" +#~ " //\n" +#~ " // a = sB / T\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ "\n" +#~ " let balance = self.token.read().balance_of(this);\n" +#~ " let amount = (shares * balance) / self.total_supply.read();\n" +#~ " PrivateFunctions::_burn(ref self, caller, shares);\n" +#~ " self.token.read().transfer(caller, amount);\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "\n" +#~ "```" + +#~ msgid "# ERC20 Token" +#~ msgstr "# ERC20 代币" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IERC20 {\n" +#~ " fn get_name(self: @TContractState) -> felt252;\n" +#~ " fn get_symbol(self: @TContractState) -> felt252;\n" +#~ " fn get_decimals(self: @TContractState) -> u8;\n" +#~ " fn get_total_supply(self: @TContractState) -> felt252;\n" +#~ " fn balance_of(self: @TContractState, account: ContractAddress) -> " +#~ "felt252;\n" +#~ " fn allowance(\n" +#~ " self: @TContractState, owner: ContractAddress, spender: " +#~ "ContractAddress\n" +#~ " ) -> felt252;\n" +#~ " fn transfer(ref self: TContractState, recipient: ContractAddress, " +#~ "amount: felt252);\n" +#~ " fn transfer_from(\n" +#~ " ref self: TContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " );\n" +#~ " fn approve(ref self: TContractState, spender: ContractAddress, " +#~ "amount: felt252);\n" +#~ " fn increase_allowance(ref self: TContractState, spender: " +#~ "ContractAddress, added_value: felt252);\n" +#~ " fn decrease_allowance(\n" +#~ " ref self: TContractState, spender: ContractAddress, " +#~ "subtracted_value: felt252\n" +#~ " );\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IERC20 {\n" +#~ " fn get_name(self: @TContractState) -> felt252;\n" +#~ " fn get_symbol(self: @TContractState) -> felt252;\n" +#~ " fn get_decimals(self: @TContractState) -> u8;\n" +#~ " fn get_total_supply(self: @TContractState) -> felt252;\n" +#~ " fn balance_of(self: @TContractState, account: ContractAddress) -> " +#~ "felt252;\n" +#~ " fn allowance(\n" +#~ " self: @TContractState, owner: ContractAddress, spender: " +#~ "ContractAddress\n" +#~ " ) -> felt252;\n" +#~ " fn transfer(ref self: TContractState, recipient: ContractAddress, " +#~ "amount: felt252);\n" +#~ " fn transfer_from(\n" +#~ " ref self: TContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " );\n" +#~ " fn approve(ref self: TContractState, spender: ContractAddress, " +#~ "amount: felt252);\n" +#~ " fn increase_allowance(ref self: TContractState, spender: " +#~ "ContractAddress, added_value: felt252);\n" +#~ " fn decrease_allowance(\n" +#~ " ref self: TContractState, spender: ContractAddress, " +#~ "subtracted_value: felt252\n" +#~ " );\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod erc20 {\n" +#~ " use zeroable::Zeroable;\n" +#~ " use starknet::get_caller_address;\n" +#~ " use starknet::contract_address_const;\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " name: felt252,\n" +#~ " symbol: felt252,\n" +#~ " decimals: u8,\n" +#~ " total_supply: felt252,\n" +#~ " balances: LegacyMap::,\n" +#~ " allowances: LegacyMap::<(ContractAddress, ContractAddress), " +#~ "felt252>,\n" +#~ " }\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Transfer: Transfer,\n" +#~ " Approval: Approval,\n" +#~ " }\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Transfer {\n" +#~ " from: ContractAddress,\n" +#~ " to: ContractAddress,\n" +#~ " value: felt252,\n" +#~ " }\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Approval {\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " value: felt252,\n" +#~ " }\n" +#~ "\n" +#~ " mod Errors {\n" +#~ " const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0';\n" +#~ " const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0';\n" +#~ " const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0';\n" +#~ " const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0';\n" +#~ " const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0';\n" +#~ " const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0';\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(\n" +#~ " ref self: ContractState,\n" +#~ " recipient: ContractAddress,\n" +#~ " name: felt252,\n" +#~ " decimals: u8,\n" +#~ " initial_supply: felt252,\n" +#~ " symbol: felt252\n" +#~ " ) {\n" +#~ " self.name.write(name);\n" +#~ " self.symbol.write(symbol);\n" +#~ " self.decimals.write(decimals);\n" +#~ " self.mint(recipient, initial_supply);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl IERC20Impl of super::IERC20 {\n" +#~ " fn get_name(self: @ContractState) -> felt252 {\n" +#~ " self.name.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_symbol(self: @ContractState) -> felt252 {\n" +#~ " self.symbol.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_decimals(self: @ContractState) -> u8 {\n" +#~ " self.decimals.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_total_supply(self: @ContractState) -> felt252 {\n" +#~ " self.total_supply.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn balance_of(self: @ContractState, account: ContractAddress) -> " +#~ "felt252 {\n" +#~ " self.balances.read(account)\n" +#~ " }\n" +#~ "\n" +#~ " fn allowance(\n" +#~ " self: @ContractState, owner: ContractAddress, spender: " +#~ "ContractAddress\n" +#~ " ) -> felt252 {\n" +#~ " self.allowances.read((owner, spender))\n" +#~ " }\n" +#~ "\n" +#~ " fn transfer(ref self: ContractState, recipient: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " let sender = get_caller_address();\n" +#~ " self._transfer(sender, recipient, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn transfer_from(\n" +#~ " ref self: ContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self.spend_allowance(sender, caller, amount);\n" +#~ " self._transfer(sender, recipient, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn approve(ref self: ContractState, spender: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self.approve_helper(caller, spender, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn increase_allowance(\n" +#~ " ref self: ContractState, spender: ContractAddress, " +#~ "added_value: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self\n" +#~ " .approve_helper(\n" +#~ " caller, spender, self.allowances.read((caller, " +#~ "spender)) + added_value\n" +#~ " );\n" +#~ " }\n" +#~ "\n" +#~ " fn decrease_allowance(\n" +#~ " ref self: ContractState, spender: ContractAddress, " +#~ "subtracted_value: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self\n" +#~ " .approve_helper(\n" +#~ " caller, spender, self.allowances.read((caller, " +#~ "spender)) - subtracted_value\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl InternalImpl of InternalTrait {\n" +#~ " fn _transfer(\n" +#~ " ref self: ContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " assert(!sender.is_zero(), Errors::TRANSFER_FROM_ZERO);\n" +#~ " assert(!recipient.is_zero(), Errors::TRANSFER_TO_ZERO);\n" +#~ " self.balances.write(sender, self.balances.read(sender) - " +#~ "amount);\n" +#~ " self.balances.write(recipient, self.balances.read(recipient) " +#~ "+ amount);\n" +#~ " self.emit(Transfer { from: sender, to: recipient, value: " +#~ "amount });\n" +#~ " }\n" +#~ "\n" +#~ " fn spend_allowance(\n" +#~ " ref self: ContractState,\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " let allowance = self.allowances.read((owner, spender));\n" +#~ " self.allowances.write((owner, spender), allowance - amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn approve_helper(\n" +#~ " ref self: ContractState,\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " assert(!spender.is_zero(), Errors::APPROVE_TO_ZERO);\n" +#~ " self.allowances.write((owner, spender), amount);\n" +#~ " self.emit(Approval { owner, spender, value: amount });\n" +#~ " }\n" +#~ "\n" +#~ " fn mint(ref self: ContractState, recipient: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " assert(!recipient.is_zero(), Errors::MINT_TO_ZERO);\n" +#~ " let supply = self.total_supply.read() + amount; // What can " +#~ "go wrong here?\n" +#~ " self.total_supply.write(supply);\n" +#~ " let balance = self.balances.read(recipient) + amount;\n" +#~ " self.balances.write(recipient, amount);\n" +#~ " self\n" +#~ " .emit(\n" +#~ " Event::Transfer(\n" +#~ " Transfer {\n" +#~ " from: contract_address_const::<0>(), to: " +#~ "recipient, value: amount\n" +#~ " }\n" +#~ " )\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::contract]\n" +#~ "mod erc20 {\n" +#~ " use zeroable::Zeroable;\n" +#~ " use starknet::get_caller_address;\n" +#~ " use starknet::contract_address_const;\n" +#~ " use starknet::ContractAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " name: felt252,\n" +#~ " symbol: felt252,\n" +#~ " decimals: u8,\n" +#~ " total_supply: felt252,\n" +#~ " balances: LegacyMap::,\n" +#~ " allowances: LegacyMap::<(ContractAddress, ContractAddress), " +#~ "felt252>,\n" +#~ " }\n" +#~ "\n" +#~ " #[event]\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " enum Event {\n" +#~ " Transfer: Transfer,\n" +#~ " Approval: Approval,\n" +#~ " }\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Transfer {\n" +#~ " from: ContractAddress,\n" +#~ " to: ContractAddress,\n" +#~ " value: felt252,\n" +#~ " }\n" +#~ " #[derive(Drop, starknet::Event)]\n" +#~ " struct Approval {\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " value: felt252,\n" +#~ " }\n" +#~ "\n" +#~ " mod Errors {\n" +#~ " const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0';\n" +#~ " const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0';\n" +#~ " const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0';\n" +#~ " const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0';\n" +#~ " const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0';\n" +#~ " const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0';\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(\n" +#~ " ref self: ContractState,\n" +#~ " recipient: ContractAddress,\n" +#~ " name: felt252,\n" +#~ " decimals: u8,\n" +#~ " initial_supply: felt252,\n" +#~ " symbol: felt252\n" +#~ " ) {\n" +#~ " self.name.write(name);\n" +#~ " self.symbol.write(symbol);\n" +#~ " self.decimals.write(decimals);\n" +#~ " self.mint(recipient, initial_supply);\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl IERC20Impl of super::IERC20 {\n" +#~ " fn get_name(self: @ContractState) -> felt252 {\n" +#~ " self.name.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_symbol(self: @ContractState) -> felt252 {\n" +#~ " self.symbol.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_decimals(self: @ContractState) -> u8 {\n" +#~ " self.decimals.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_total_supply(self: @ContractState) -> felt252 {\n" +#~ " self.total_supply.read()\n" +#~ " }\n" +#~ "\n" +#~ " fn balance_of(self: @ContractState, account: ContractAddress) -> " +#~ "felt252 {\n" +#~ " self.balances.read(account)\n" +#~ " }\n" +#~ "\n" +#~ " fn allowance(\n" +#~ " self: @ContractState, owner: ContractAddress, spender: " +#~ "ContractAddress\n" +#~ " ) -> felt252 {\n" +#~ " self.allowances.read((owner, spender))\n" +#~ " }\n" +#~ "\n" +#~ " fn transfer(ref self: ContractState, recipient: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " let sender = get_caller_address();\n" +#~ " self._transfer(sender, recipient, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn transfer_from(\n" +#~ " ref self: ContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self.spend_allowance(sender, caller, amount);\n" +#~ " self._transfer(sender, recipient, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn approve(ref self: ContractState, spender: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self.approve_helper(caller, spender, amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn increase_allowance(\n" +#~ " ref self: ContractState, spender: ContractAddress, " +#~ "added_value: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self\n" +#~ " .approve_helper(\n" +#~ " caller, spender, self.allowances.read((caller, " +#~ "spender)) + added_value\n" +#~ " );\n" +#~ " }\n" +#~ "\n" +#~ " fn decrease_allowance(\n" +#~ " ref self: ContractState, spender: ContractAddress, " +#~ "subtracted_value: felt252\n" +#~ " ) {\n" +#~ " let caller = get_caller_address();\n" +#~ " self\n" +#~ " .approve_helper(\n" +#~ " caller, spender, self.allowances.read((caller, " +#~ "spender)) - subtracted_value\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl InternalImpl of InternalTrait {\n" +#~ " fn _transfer(\n" +#~ " ref self: ContractState,\n" +#~ " sender: ContractAddress,\n" +#~ " recipient: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " assert(!sender.is_zero(), Errors::TRANSFER_FROM_ZERO);\n" +#~ " assert(!recipient.is_zero(), Errors::TRANSFER_TO_ZERO);\n" +#~ " self.balances.write(sender, self.balances.read(sender) - " +#~ "amount);\n" +#~ " self.balances.write(recipient, self.balances.read(recipient) " +#~ "+ amount);\n" +#~ " self.emit(Transfer { from: sender, to: recipient, value: " +#~ "amount });\n" +#~ " }\n" +#~ "\n" +#~ " fn spend_allowance(\n" +#~ " ref self: ContractState,\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " let allowance = self.allowances.read((owner, spender));\n" +#~ " self.allowances.write((owner, spender), allowance - amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn approve_helper(\n" +#~ " ref self: ContractState,\n" +#~ " owner: ContractAddress,\n" +#~ " spender: ContractAddress,\n" +#~ " amount: felt252\n" +#~ " ) {\n" +#~ " assert(!spender.is_zero(), Errors::APPROVE_TO_ZERO);\n" +#~ " self.allowances.write((owner, spender), amount);\n" +#~ " self.emit(Approval { owner, spender, value: amount });\n" +#~ " }\n" +#~ "\n" +#~ " fn mint(ref self: ContractState, recipient: ContractAddress, " +#~ "amount: felt252) {\n" +#~ " assert(!recipient.is_zero(), Errors::MINT_TO_ZERO);\n" +#~ " let supply = self.total_supply.read() + amount; // What can " +#~ "go wrong here?\n" +#~ " self.total_supply.write(supply);\n" +#~ " let balance = self.balances.read(recipient) + amount;\n" +#~ " self.balances.write(recipient, amount);\n" +#~ " self\n" +#~ " .emit(\n" +#~ " Event::Transfer(\n" +#~ " Transfer {\n" +#~ " from: contract_address_const::<0>(), to: " +#~ "recipient, value: amount\n" +#~ " }\n" +#~ " )\n" +#~ " );\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-10-24
" +#~ msgstr "
Last change: 2023-10-24
" + +#~ msgid "# Constant Product AMM" +#~ msgstr "# 恒定乘积自动做市商" + +#~ msgid "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IConstantProductAmm {\n" +#~ " fn swap(ref self: TContractState, token_in: ContractAddress, " +#~ "amount_in: u256) -> u256;\n" +#~ " fn add_liquidity(ref self: TContractState, amount0: u256, amount1: " +#~ "u256) -> u256;\n" +#~ " fn remove_liquidity(ref self: TContractState, shares: u256) -> (u256, " +#~ "u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ConstantProductAmm {\n" +#~ " use core::traits::Into;\n" +#~ " use openzeppelin::token::erc20::interface::{IERC20Dispatcher, " +#~ "IERC20DispatcherTrait};\n" +#~ " use starknet::{\n" +#~ " ContractAddress, get_caller_address, get_contract_address, " +#~ "contract_address_const\n" +#~ " };\n" +#~ " use integer::u256_sqrt;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " token0: IERC20Dispatcher,\n" +#~ " token1: IERC20Dispatcher,\n" +#~ " reserve0: u256,\n" +#~ " reserve1: u256,\n" +#~ " total_supply: u256,\n" +#~ " balance_of: LegacyMap::,\n" +#~ " // Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" +#~ " // E.g. 3 = 0.3%\n" +#~ " fee: u16,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(\n" +#~ " ref self: ContractState, token0: ContractAddress, token1: " +#~ "ContractAddress, fee: u16\n" +#~ " ) {\n" +#~ " // assert(fee <= 1000, 'fee > 1000');\n" +#~ " self.token0.write(IERC20Dispatcher { contract_address: " +#~ "token0 });\n" +#~ " self.token1.write(IERC20Dispatcher { contract_address: " +#~ "token1 });\n" +#~ " self.fee.write(fee);\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " fn _mint(ref self: ContractState, to: ContractAddress, amount: " +#~ "u256) {\n" +#~ " self.balance_of.write(to, self.balance_of.read(to) + " +#~ "amount);\n" +#~ " self.total_supply.write(self.total_supply.read() + amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn _burn(ref self: ContractState, from: ContractAddress, amount: " +#~ "u256) {\n" +#~ " self.balance_of.write(from, self.balance_of.read(from) - " +#~ "amount);\n" +#~ " self.total_supply.write(self.total_supply.read() - amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn _update(ref self: ContractState, reserve0: u256, reserve1: " +#~ "u256) {\n" +#~ " self.reserve0.write(reserve0);\n" +#~ " self.reserve1.write(reserve1);\n" +#~ " }\n" +#~ "\n" +#~ " #[inline(always)]\n" +#~ " fn select_token(self: @ContractState, token: ContractAddress) -> " +#~ "bool {\n" +#~ " assert(\n" +#~ " token == self.token0.read().contract_address\n" +#~ " || token == self.token1.read().contract_address,\n" +#~ " 'invalid token'\n" +#~ " );\n" +#~ " token == self.token0.read().contract_address\n" +#~ " }\n" +#~ "\n" +#~ " #[inline(always)]\n" +#~ " fn min(x: u256, y: u256) -> u256 {\n" +#~ " if (x <= y) {\n" +#~ " x\n" +#~ " } else {\n" +#~ " y\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ConstantProductAmm of super::IConstantProductAmm " +#~ "{\n" +#~ " fn swap(ref self: ContractState, token_in: ContractAddress, " +#~ "amount_in: u256) -> u256 {\n" +#~ " assert(amount_in > 0, 'amount in = 0');\n" +#~ " let is_token0: bool = self.select_token(token_in);\n" +#~ "\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ " let (reserve0, reserve1): (u256, u256) = (self.reserve0." +#~ "read(), self.reserve1.read());\n" +#~ " let (\n" +#~ " token_in, token_out, reserve_in, reserve_out\n" +#~ " ): (IERC20Dispatcher, IERC20Dispatcher, u256, u256) =\n" +#~ " if (is_token0) {\n" +#~ " (token0, token1, reserve0, reserve1)\n" +#~ " } else {\n" +#~ " (token1, token0, reserve1, reserve0)\n" +#~ " };\n" +#~ "\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " token_in.transfer_from(caller, this, amount_in);\n" +#~ "\n" +#~ " // How much dy for dx?\n" +#~ " // xy = k\n" +#~ " // (x + dx)(y - dy) = k\n" +#~ " // y - dy = k / (x + dx)\n" +#~ " // y - k / (x + dx) = dy\n" +#~ " // y - xy / (x + dx) = dy\n" +#~ " // (yx + ydx - xy) / (x + dx) = dy\n" +#~ " // ydx / (x + dx) = dy\n" +#~ "\n" +#~ " let amount_in_with_fee = (amount_in * (1000 - self.fee.read()." +#~ "into()) / 1000);\n" +#~ " let amount_out = (reserve_out * amount_in_with_fee) / " +#~ "(reserve_in + amount_in_with_fee);\n" +#~ "\n" +#~ " token_out.transfer(caller, amount_out);\n" +#~ "\n" +#~ " self._update(self.token0.read().balance_of(this), self.token1." +#~ "read().balance_of(this));\n" +#~ " amount_out\n" +#~ " }\n" +#~ "\n" +#~ " fn add_liquidity(ref self: ContractState, amount0: u256, amount1: " +#~ "u256) -> u256 {\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ "\n" +#~ " token0.transfer_from(caller, this, amount0);\n" +#~ " token1.transfer_from(caller, this, amount1);\n" +#~ "\n" +#~ " // How much dx, dy to add?\n" +#~ " //\n" +#~ " // xy = k\n" +#~ " // (x + dx)(y + dy) = k'\n" +#~ " //\n" +#~ " // No price change, before and after adding liquidity\n" +#~ " // x / y = (x + dx) / (y + dy)\n" +#~ " //\n" +#~ " // x(y + dy) = y(x + dx)\n" +#~ " // x * dy = y * dx\n" +#~ " //\n" +#~ " // x / y = dx / dy\n" +#~ " // dy = y / x * dx\n" +#~ "\n" +#~ " let (reserve0, reserve1): (u256, u256) = (self.reserve0." +#~ "read(), self.reserve1.read());\n" +#~ " if (reserve0 > 0 || reserve1 > 0) {\n" +#~ " assert(reserve0 * amount1 == reserve1 * amount0, 'x / y !" +#~ "= dx / dy');\n" +#~ " }\n" +#~ "\n" +#~ " // How much shares to mint?\n" +#~ " //\n" +#~ " // f(x, y) = value of liquidity\n" +#~ " // We will define f(x, y) = sqrt(xy)\n" +#~ " //\n" +#~ " // L0 = f(x, y)\n" +#~ " // L1 = f(x + dx, y + dy)\n" +#~ " // T = total shares\n" +#~ " // s = shares to mint\n" +#~ " //\n" +#~ " // Total shares should increase proportional to increase in " +#~ "liquidity\n" +#~ " // L1 / L0 = (T + s) / T\n" +#~ " //\n" +#~ " // L1 * T = L0 * (T + s)\n" +#~ " //\n" +#~ " // (L1 - L0) * T / L0 = s\n" +#~ "\n" +#~ " // Claim\n" +#~ " // (L1 - L0) / L0 = dx / x = dy / y\n" +#~ " //\n" +#~ " // Proof\n" +#~ " // --- Equation 1 ---\n" +#~ " // (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / " +#~ "sqrt(xy)\n" +#~ " //\n" +#~ " // dx / dy = x / y so replace dy = dx * y / x\n" +#~ " //\n" +#~ " // --- Equation 2 ---\n" +#~ " // Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / " +#~ "sqrt(xy)\n" +#~ " //\n" +#~ " // Multiply by sqrt(x) / sqrt(x)\n" +#~ " // Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - " +#~ "sqrt(x^2y)) / sqrt(x^2y)\n" +#~ " // = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - " +#~ "sqrt(x^2)) / (sqrt(y)sqrt(x^2))\n" +#~ " // sqrt(y) on top and bottom cancels out\n" +#~ " //\n" +#~ " // --- Equation 3 ---\n" +#~ " // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +#~ "(sqrt(x^2)\n" +#~ " // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)\n" +#~ " // = ((x + dx) - x) / x\n" +#~ " // = dx / x\n" +#~ " // Since dx / dy = x / y,\n" +#~ " // dx / x = dy / y\n" +#~ " //\n" +#~ " // Finally\n" +#~ " // (L1 - L0) / L0 = dx / x = dy / y\n" +#~ "\n" +#~ " let total_supply = self.total_supply.read();\n" +#~ " let shares = if (total_supply == 0) {\n" +#~ " u256_sqrt(amount0 * amount1).into()\n" +#~ " } else {\n" +#~ " PrivateFunctions::min(\n" +#~ " amount0 * total_supply / reserve0, amount1 * " +#~ "total_supply / reserve1\n" +#~ " )\n" +#~ " };\n" +#~ " assert(shares > 0, 'shares = 0');\n" +#~ " self._mint(caller, shares);\n" +#~ "\n" +#~ " self._update(self.token0.read().balance_of(this), self.token1." +#~ "read().balance_of(this));\n" +#~ " shares\n" +#~ " }\n" +#~ "\n" +#~ " fn remove_liquidity(ref self: ContractState, shares: u256) -> " +#~ "(u256, u256) {\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ "\n" +#~ " // Claim\n" +#~ " // dx, dy = amount of liquidity to remove\n" +#~ " // dx = s / T * x\n" +#~ " // dy = s / T * y\n" +#~ " //\n" +#~ " // Proof\n" +#~ " // Let's find dx, dy such that\n" +#~ " // v / L = s / T\n" +#~ " //\n" +#~ " // where\n" +#~ " // v = f(dx, dy) = sqrt(dxdy)\n" +#~ " // L = total liquidity = sqrt(xy)\n" +#~ " // s = shares\n" +#~ " // T = total supply\n" +#~ " //\n" +#~ " // --- Equation 1 ---\n" +#~ " // v = s / T * L\n" +#~ " // sqrt(dxdy) = s / T * sqrt(xy)\n" +#~ " //\n" +#~ " // Amount of liquidity to remove must not change price so\n" +#~ " // dx / dy = x / y\n" +#~ " //\n" +#~ " // replace dy = dx * y / x\n" +#~ " // sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)\n" +#~ " //\n" +#~ " // Divide both sides of Equation 1 with sqrt(y / x)\n" +#~ " // dx = s / T * sqrt(xy) / sqrt(y / x)\n" +#~ " // = s / T * sqrt(x^2) = s / T * x\n" +#~ " //\n" +#~ " // Likewise\n" +#~ " // dy = s / T * y\n" +#~ "\n" +#~ " // bal0 >= reserve0\n" +#~ " // bal1 >= reserve1\n" +#~ " let (bal0, bal1): (u256, u256) = (token0.balance_of(this), " +#~ "token1.balance_of(this));\n" +#~ "\n" +#~ " let total_supply = self.total_supply.read();\n" +#~ " let (amount0, amount1): (u256, u256) = (\n" +#~ " (shares * bal0) / total_supply, (shares * bal1) / " +#~ "total_supply\n" +#~ " );\n" +#~ " assert(amount0 > 0 && amount1 > 0, 'amount0 or amount1 = " +#~ "0');\n" +#~ "\n" +#~ " self._burn(caller, shares);\n" +#~ " self._update(bal0 - amount0, bal1 - amount1);\n" +#~ "\n" +#~ " token0.transfer(caller, amount0);\n" +#~ " token1.transfer(caller, amount1);\n" +#~ " (amount0, amount1)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "use starknet::ContractAddress;\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IConstantProductAmm {\n" +#~ " fn swap(ref self: TContractState, token_in: ContractAddress, " +#~ "amount_in: u256) -> u256;\n" +#~ " fn add_liquidity(ref self: TContractState, amount0: u256, amount1: " +#~ "u256) -> u256;\n" +#~ " fn remove_liquidity(ref self: TContractState, shares: u256) -> (u256, " +#~ "u256);\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ConstantProductAmm {\n" +#~ " use core::traits::Into;\n" +#~ " use openzeppelin::token::erc20::interface::{IERC20Dispatcher, " +#~ "IERC20DispatcherTrait};\n" +#~ " use starknet::{\n" +#~ " ContractAddress, get_caller_address, get_contract_address, " +#~ "contract_address_const\n" +#~ " };\n" +#~ " use integer::u256_sqrt;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " token0: IERC20Dispatcher,\n" +#~ " token1: IERC20Dispatcher,\n" +#~ " reserve0: u256,\n" +#~ " reserve1: u256,\n" +#~ " total_supply: u256,\n" +#~ " balance_of: LegacyMap::,\n" +#~ " // Fee 0 - 1000 (0% - 100%, 1 decimal places)\n" +#~ " // E.g. 3 = 0.3%\n" +#~ " fee: u16,\n" +#~ " }\n" +#~ "\n" +#~ " #[constructor]\n" +#~ " fn constructor(\n" +#~ " ref self: ContractState, token0: ContractAddress, token1: " +#~ "ContractAddress, fee: u16\n" +#~ " ) {\n" +#~ " // assert(fee <= 1000, 'fee > 1000');\n" +#~ " self.token0.write(IERC20Dispatcher { contract_address: " +#~ "token0 });\n" +#~ " self.token1.write(IERC20Dispatcher { contract_address: " +#~ "token1 });\n" +#~ " self.fee.write(fee);\n" +#~ " }\n" +#~ "\n" +#~ " #[generate_trait]\n" +#~ " impl PrivateFunctions of PrivateFunctionsTrait {\n" +#~ " fn _mint(ref self: ContractState, to: ContractAddress, amount: " +#~ "u256) {\n" +#~ " self.balance_of.write(to, self.balance_of.read(to) + " +#~ "amount);\n" +#~ " self.total_supply.write(self.total_supply.read() + amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn _burn(ref self: ContractState, from: ContractAddress, amount: " +#~ "u256) {\n" +#~ " self.balance_of.write(from, self.balance_of.read(from) - " +#~ "amount);\n" +#~ " self.total_supply.write(self.total_supply.read() - amount);\n" +#~ " }\n" +#~ "\n" +#~ " fn _update(ref self: ContractState, reserve0: u256, reserve1: " +#~ "u256) {\n" +#~ " self.reserve0.write(reserve0);\n" +#~ " self.reserve1.write(reserve1);\n" +#~ " }\n" +#~ "\n" +#~ " #[inline(always)]\n" +#~ " fn select_token(self: @ContractState, token: ContractAddress) -> " +#~ "bool {\n" +#~ " assert(\n" +#~ " token == self.token0.read().contract_address\n" +#~ " || token == self.token1.read().contract_address,\n" +#~ " 'invalid token'\n" +#~ " );\n" +#~ " token == self.token0.read().contract_address\n" +#~ " }\n" +#~ "\n" +#~ " #[inline(always)]\n" +#~ " fn min(x: u256, y: u256) -> u256 {\n" +#~ " if (x <= y) {\n" +#~ " x\n" +#~ " } else {\n" +#~ " y\n" +#~ " }\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ConstantProductAmm of super::IConstantProductAmm " +#~ "{\n" +#~ " fn swap(ref self: ContractState, token_in: ContractAddress, " +#~ "amount_in: u256) -> u256 {\n" +#~ " assert(amount_in > 0, 'amount in = 0');\n" +#~ " let is_token0: bool = self.select_token(token_in);\n" +#~ "\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ " let (reserve0, reserve1): (u256, u256) = (self.reserve0." +#~ "read(), self.reserve1.read());\n" +#~ " let (\n" +#~ " token_in, token_out, reserve_in, reserve_out\n" +#~ " ): (IERC20Dispatcher, IERC20Dispatcher, u256, u256) =\n" +#~ " if (is_token0) {\n" +#~ " (token0, token1, reserve0, reserve1)\n" +#~ " } else {\n" +#~ " (token1, token0, reserve1, reserve0)\n" +#~ " };\n" +#~ "\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " token_in.transfer_from(caller, this, amount_in);\n" +#~ "\n" +#~ " // How much dy for dx?\n" +#~ " // xy = k\n" +#~ " // (x + dx)(y - dy) = k\n" +#~ " // y - dy = k / (x + dx)\n" +#~ " // y - k / (x + dx) = dy\n" +#~ " // y - xy / (x + dx) = dy\n" +#~ " // (yx + ydx - xy) / (x + dx) = dy\n" +#~ " // ydx / (x + dx) = dy\n" +#~ "\n" +#~ " let amount_in_with_fee = (amount_in * (1000 - self.fee.read()." +#~ "into()) / 1000);\n" +#~ " let amount_out = (reserve_out * amount_in_with_fee) / " +#~ "(reserve_in + amount_in_with_fee);\n" +#~ "\n" +#~ " token_out.transfer(caller, amount_out);\n" +#~ "\n" +#~ " self._update(self.token0.read().balance_of(this), self.token1." +#~ "read().balance_of(this));\n" +#~ " amount_out\n" +#~ " }\n" +#~ "\n" +#~ " fn add_liquidity(ref self: ContractState, amount0: u256, amount1: " +#~ "u256) -> u256 {\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ "\n" +#~ " token0.transfer_from(caller, this, amount0);\n" +#~ " token1.transfer_from(caller, this, amount1);\n" +#~ "\n" +#~ " // How much dx, dy to add?\n" +#~ " //\n" +#~ " // xy = k\n" +#~ " // (x + dx)(y + dy) = k'\n" +#~ " //\n" +#~ " // No price change, before and after adding liquidity\n" +#~ " // x / y = (x + dx) / (y + dy)\n" +#~ " //\n" +#~ " // x(y + dy) = y(x + dx)\n" +#~ " // x * dy = y * dx\n" +#~ " //\n" +#~ " // x / y = dx / dy\n" +#~ " // dy = y / x * dx\n" +#~ "\n" +#~ " let (reserve0, reserve1): (u256, u256) = (self.reserve0." +#~ "read(), self.reserve1.read());\n" +#~ " if (reserve0 > 0 || reserve1 > 0) {\n" +#~ " assert(reserve0 * amount1 == reserve1 * amount0, 'x / y !" +#~ "= dx / dy');\n" +#~ " }\n" +#~ "\n" +#~ " // How much shares to mint?\n" +#~ " //\n" +#~ " // f(x, y) = value of liquidity\n" +#~ " // We will define f(x, y) = sqrt(xy)\n" +#~ " //\n" +#~ " // L0 = f(x, y)\n" +#~ " // L1 = f(x + dx, y + dy)\n" +#~ " // T = total shares\n" +#~ " // s = shares to mint\n" +#~ " //\n" +#~ " // Total shares should increase proportional to increase in " +#~ "liquidity\n" +#~ " // L1 / L0 = (T + s) / T\n" +#~ " //\n" +#~ " // L1 * T = L0 * (T + s)\n" +#~ " //\n" +#~ " // (L1 - L0) * T / L0 = s\n" +#~ "\n" +#~ " // Claim\n" +#~ " // (L1 - L0) / L0 = dx / x = dy / y\n" +#~ " //\n" +#~ " // Proof\n" +#~ " // --- Equation 1 ---\n" +#~ " // (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / " +#~ "sqrt(xy)\n" +#~ " //\n" +#~ " // dx / dy = x / y so replace dy = dx * y / x\n" +#~ " //\n" +#~ " // --- Equation 2 ---\n" +#~ " // Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / " +#~ "sqrt(xy)\n" +#~ " //\n" +#~ " // Multiply by sqrt(x) / sqrt(x)\n" +#~ " // Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - " +#~ "sqrt(x^2y)) / sqrt(x^2y)\n" +#~ " // = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - " +#~ "sqrt(x^2)) / (sqrt(y)sqrt(x^2))\n" +#~ " // sqrt(y) on top and bottom cancels out\n" +#~ " //\n" +#~ " // --- Equation 3 ---\n" +#~ " // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / " +#~ "(sqrt(x^2)\n" +#~ " // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)\n" +#~ " // = ((x + dx) - x) / x\n" +#~ " // = dx / x\n" +#~ " // Since dx / dy = x / y,\n" +#~ " // dx / x = dy / y\n" +#~ " //\n" +#~ " // Finally\n" +#~ " // (L1 - L0) / L0 = dx / x = dy / y\n" +#~ "\n" +#~ " let total_supply = self.total_supply.read();\n" +#~ " let shares = if (total_supply == 0) {\n" +#~ " u256_sqrt(amount0 * amount1).into()\n" +#~ " } else {\n" +#~ " PrivateFunctions::min(\n" +#~ " amount0 * total_supply / reserve0, amount1 * " +#~ "total_supply / reserve1\n" +#~ " )\n" +#~ " };\n" +#~ " assert(shares > 0, 'shares = 0');\n" +#~ " self._mint(caller, shares);\n" +#~ "\n" +#~ " self._update(self.token0.read().balance_of(this), self.token1." +#~ "read().balance_of(this));\n" +#~ " shares\n" +#~ " }\n" +#~ "\n" +#~ " fn remove_liquidity(ref self: ContractState, shares: u256) -> " +#~ "(u256, u256) {\n" +#~ " let caller = get_caller_address();\n" +#~ " let this = get_contract_address();\n" +#~ " let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = " +#~ "(\n" +#~ " self.token0.read(), self.token1.read()\n" +#~ " );\n" +#~ "\n" +#~ " // Claim\n" +#~ " // dx, dy = amount of liquidity to remove\n" +#~ " // dx = s / T * x\n" +#~ " // dy = s / T * y\n" +#~ " //\n" +#~ " // Proof\n" +#~ " // Let's find dx, dy such that\n" +#~ " // v / L = s / T\n" +#~ " //\n" +#~ " // where\n" +#~ " // v = f(dx, dy) = sqrt(dxdy)\n" +#~ " // L = total liquidity = sqrt(xy)\n" +#~ " // s = shares\n" +#~ " // T = total supply\n" +#~ " //\n" +#~ " // --- Equation 1 ---\n" +#~ " // v = s / T * L\n" +#~ " // sqrt(dxdy) = s / T * sqrt(xy)\n" +#~ " //\n" +#~ " // Amount of liquidity to remove must not change price so\n" +#~ " // dx / dy = x / y\n" +#~ " //\n" +#~ " // replace dy = dx * y / x\n" +#~ " // sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)\n" +#~ " //\n" +#~ " // Divide both sides of Equation 1 with sqrt(y / x)\n" +#~ " // dx = s / T * sqrt(xy) / sqrt(y / x)\n" +#~ " // = s / T * sqrt(x^2) = s / T * x\n" +#~ " //\n" +#~ " // Likewise\n" +#~ " // dy = s / T * y\n" +#~ "\n" +#~ " // bal0 >= reserve0\n" +#~ " // bal1 >= reserve1\n" +#~ " let (bal0, bal1): (u256, u256) = (token0.balance_of(this), " +#~ "token1.balance_of(this));\n" +#~ "\n" +#~ " let total_supply = self.total_supply.read();\n" +#~ " let (amount0, amount1): (u256, u256) = (\n" +#~ " (shares * bal0) / total_supply, (shares * bal1) / " +#~ "total_supply\n" +#~ " );\n" +#~ " assert(amount0 > 0 && amount1 > 0, 'amount0 or amount1 = " +#~ "0');\n" +#~ "\n" +#~ " self._burn(caller, shares);\n" +#~ " self._update(bal0 - amount0, bal1 - amount1);\n" +#~ "\n" +#~ " token0.transfer(caller, amount0);\n" +#~ " token1.transfer(caller, amount1);\n" +#~ " (amount0, amount1)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Writing to any storage slot" +#~ msgstr "# 写入任何存储槽" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IWriteToAnySlots {\n" +#~ " fn write_slot(ref self: TContractState, value: u32);\n" +#~ " fn read_slot(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod WriteToAnySlot {\n" +#~ " use starknet::syscalls::{storage_read_syscall, " +#~ "storage_write_syscall};\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ " use poseidon::poseidon_hash_span;\n" +#~ " use starknet::storage_access::Felt252TryIntoStorageAddress;\n" +#~ " use starknet::StorageAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " const SLOT_NAME: felt252 = 'test_slot';\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl WriteToAnySlot of super::IWriteToAnySlots {\n" +#~ " fn write_slot(ref self: ContractState, value: u32) {\n" +#~ " storage_write_syscall(0, get_address_from_name(SLOT_NAME), " +#~ "value.into());\n" +#~ " }\n" +#~ "\n" +#~ " fn read_slot(self: @ContractState) -> u32 {\n" +#~ " storage_read_syscall(0, get_address_from_name(SLOT_NAME))\n" +#~ " .unwrap_syscall()\n" +#~ " .try_into()\n" +#~ " .unwrap()\n" +#~ " }\n" +#~ " }\n" +#~ " fn get_address_from_name(variable_name: felt252) -> StorageAddress {\n" +#~ " let mut data: Array = ArrayTrait::new();\n" +#~ " data.append(variable_name);\n" +#~ " let hashed_name: felt252 = poseidon_hash_span(data.span());\n" +#~ " let MASK_250: u256 = " +#~ "0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n" +#~ " // By taking the 250 least significant bits of the hash output, " +#~ "we get a valid 250bits storage address.\n" +#~ " let result: felt252 = (hashed_name.into() & MASK_250).try_into()." +#~ "unwrap();\n" +#~ " let result: StorageAddress = result.try_into().unwrap();\n" +#~ " result\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IWriteToAnySlots {\n" +#~ " fn write_slot(ref self: TContractState, value: u32);\n" +#~ " fn read_slot(self: @TContractState) -> u32;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod WriteToAnySlot {\n" +#~ " use starknet::syscalls::{storage_read_syscall, " +#~ "storage_write_syscall};\n" +#~ " use starknet::SyscallResultTrait;\n" +#~ " use poseidon::poseidon_hash_span;\n" +#~ " use starknet::storage_access::Felt252TryIntoStorageAddress;\n" +#~ " use starknet::StorageAddress;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " const SLOT_NAME: felt252 = 'test_slot';\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl WriteToAnySlot of super::IWriteToAnySlots {\n" +#~ " fn write_slot(ref self: ContractState, value: u32) {\n" +#~ " storage_write_syscall(0, get_address_from_name(SLOT_NAME), " +#~ "value.into());\n" +#~ " }\n" +#~ "\n" +#~ " fn read_slot(self: @ContractState) -> u32 {\n" +#~ " storage_read_syscall(0, get_address_from_name(SLOT_NAME))\n" +#~ " .unwrap_syscall()\n" +#~ " .try_into()\n" +#~ " .unwrap()\n" +#~ " }\n" +#~ " }\n" +#~ " fn get_address_from_name(variable_name: felt252) -> StorageAddress {\n" +#~ " let mut data: Array = ArrayTrait::new();\n" +#~ " data.append(variable_name);\n" +#~ " let hashed_name: felt252 = poseidon_hash_span(data.span());\n" +#~ " let MASK_250: u256 = " +#~ "0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n" +#~ " // By taking the 250 least significant bits of the hash output, " +#~ "we get a valid 250bits storage address.\n" +#~ " let result: felt252 = (hashed_name.into() & MASK_250).try_into()." +#~ "unwrap();\n" +#~ " let result: StorageAddress = result.try_into().unwrap();\n" +#~ " result\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Storing Arrays" +#~ msgstr "# 存储数组" + +#~ msgid "" +#~ "```rust\n" +#~ "impl StoreFelt252Array of Store> {\n" +#~ " fn read(address_domain: u32, base: StorageBaseAddress) -> " +#~ "SyscallResult> {\n" +#~ " StoreFelt252Array::read_at_offset(address_domain, base, 0)\n" +#~ " }\n" +#~ "\n" +#~ " fn write(\n" +#~ " address_domain: u32, base: StorageBaseAddress, value: " +#~ "Array\n" +#~ " ) -> SyscallResult<()> {\n" +#~ " StoreFelt252Array::write_at_offset(address_domain, base, 0, " +#~ "value)\n" +#~ " }\n" +#~ "\n" +#~ " fn read_at_offset(\n" +#~ " address_domain: u32, base: StorageBaseAddress, mut offset: u8\n" +#~ " ) -> SyscallResult> {\n" +#~ " let mut arr: Array = ArrayTrait::new();\n" +#~ "\n" +#~ " // Read the stored array's length. If the length is superior to " +#~ "255, the read will fail.\n" +#~ " let len: u8 = Store::::read_at_offset(address_domain, base, " +#~ "offset)\n" +#~ " .expect('Storage Span too large');\n" +#~ " offset += 1;\n" +#~ "\n" +#~ " // Sequentially read all stored elements and append them to the " +#~ "array.\n" +#~ " let exit = len + offset;\n" +#~ " loop {\n" +#~ " if offset >= exit {\n" +#~ " break;\n" +#~ " }\n" +#~ "\n" +#~ " let value = Store::::read_at_offset(address_domain, " +#~ "base, offset).unwrap();\n" +#~ " arr.append(value);\n" +#~ " offset += Store::::size();\n" +#~ " };\n" +#~ "\n" +#~ " // Return the array.\n" +#~ " Result::Ok(arr)\n" +#~ " }\n" +#~ "\n" +#~ " fn write_at_offset(\n" +#~ " address_domain: u32, base: StorageBaseAddress, mut offset: u8, " +#~ "mut value: Array\n" +#~ " ) -> SyscallResult<()> {\n" +#~ " // // Store the length of the array in the first storage slot.\n" +#~ " let len: u8 = value.len().try_into().expect('Storage - Span too " +#~ "large');\n" +#~ " Store::::write_at_offset(address_domain, base, offset, len);\n" +#~ " offset += 1;\n" +#~ "\n" +#~ " // Store the array elements sequentially\n" +#~ " loop {\n" +#~ " match value.pop_front() {\n" +#~ " Option::Some(element) => {\n" +#~ " Store::::write_at_offset(address_domain, " +#~ "base, offset, element);\n" +#~ " offset += Store::::size();\n" +#~ " },\n" +#~ " Option::None(_) => { break Result::Ok(()); }\n" +#~ " };\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " fn size() -> u8 {\n" +#~ " 255 * Store::::size()\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "impl StoreFelt252Array of Store> {\n" +#~ " fn read(address_domain: u32, base: StorageBaseAddress) -> " +#~ "SyscallResult> {\n" +#~ " StoreFelt252Array::read_at_offset(address_domain, base, 0)\n" +#~ " }\n" +#~ "\n" +#~ " fn write(\n" +#~ " address_domain: u32, base: StorageBaseAddress, value: " +#~ "Array\n" +#~ " ) -> SyscallResult<()> {\n" +#~ " StoreFelt252Array::write_at_offset(address_domain, base, 0, " +#~ "value)\n" +#~ " }\n" +#~ "\n" +#~ " fn read_at_offset(\n" +#~ " address_domain: u32, base: StorageBaseAddress, mut offset: u8\n" +#~ " ) -> SyscallResult> {\n" +#~ " let mut arr: Array = ArrayTrait::new();\n" +#~ "\n" +#~ " // Read the stored array's length. If the length is superior to " +#~ "255, the read will fail.\n" +#~ " let len: u8 = Store::::read_at_offset(address_domain, base, " +#~ "offset)\n" +#~ " .expect('Storage Span too large');\n" +#~ " offset += 1;\n" +#~ "\n" +#~ " // Sequentially read all stored elements and append them to the " +#~ "array.\n" +#~ " let exit = len + offset;\n" +#~ " loop {\n" +#~ " if offset >= exit {\n" +#~ " break;\n" +#~ " }\n" +#~ "\n" +#~ " let value = Store::::read_at_offset(address_domain, " +#~ "base, offset).unwrap();\n" +#~ " arr.append(value);\n" +#~ " offset += Store::::size();\n" +#~ " };\n" +#~ "\n" +#~ " // Return the array.\n" +#~ " Result::Ok(arr)\n" +#~ " }\n" +#~ "\n" +#~ " fn write_at_offset(\n" +#~ " address_domain: u32, base: StorageBaseAddress, mut offset: u8, " +#~ "mut value: Array\n" +#~ " ) -> SyscallResult<()> {\n" +#~ " // // Store the length of the array in the first storage slot.\n" +#~ " let len: u8 = value.len().try_into().expect('Storage - Span too " +#~ "large');\n" +#~ " Store::::write_at_offset(address_domain, base, offset, len);\n" +#~ " offset += 1;\n" +#~ "\n" +#~ " // Store the array elements sequentially\n" +#~ " loop {\n" +#~ " match value.pop_front() {\n" +#~ " Option::Some(element) => {\n" +#~ " Store::::write_at_offset(address_domain, " +#~ "base, offset, element);\n" +#~ " offset += Store::::size();\n" +#~ " },\n" +#~ " Option::None(_) => { break Result::Ok(()); }\n" +#~ " };\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " fn size() -> u8 {\n" +#~ " 255 * Store::::size()\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStoreArrayContract {\n" +#~ " fn store_array(ref self: TContractState, arr: Array);\n" +#~ " fn read_array(self: @TContractState) -> Array;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod StoreArrayContract {\n" +#~ " use super::StoreFelt252Array;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " arr: Array\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StoreArrayImpl of super::IStoreArrayContract {\n" +#~ " fn store_array(ref self: ContractState, arr: Array) {\n" +#~ " self.arr.write(arr);\n" +#~ " }\n" +#~ "\n" +#~ " fn read_array(self: @ContractState) -> Array {\n" +#~ " self.arr.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IStoreArrayContract {\n" +#~ " fn store_array(ref self: TContractState, arr: Array);\n" +#~ " fn read_array(self: @TContractState) -> Array;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod StoreArrayContract {\n" +#~ " use super::StoreFelt252Array;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " arr: Array\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl StoreArrayImpl of super::IStoreArrayContract {\n" +#~ " fn store_array(ref self: ContractState, arr: Array) {\n" +#~ " self.arr.write(arr);\n" +#~ " }\n" +#~ "\n" +#~ " fn read_array(self: @ContractState) -> Array {\n" +#~ " self.arr.read()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[derive(Copy, Drop, Serde, Hash)]\n" +#~ "struct Pet {\n" +#~ " name: felt252,\n" +#~ " age: u8,\n" +#~ " owner: felt252,\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IPetRegistry {\n" +#~ " fn register_pet(ref self: TContractState, key: Pet, timestamp: u64);\n" +#~ " fn get_registration_date(self: @TContractState, key: Pet) -> u64;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod PetRegistry {\n" +#~ " use hash::{HashStateTrait, Hash};\n" +#~ " use super::Pet;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " registration_time: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl PetRegistry of super::IPetRegistry {\n" +#~ " fn register_pet(ref self: ContractState, key: Pet, timestamp: " +#~ "u64) {\n" +#~ " self.registration_time.write(key, timestamp);\n" +#~ " }\n" +#~ "\n" +#~ " fn get_registration_date(self: @ContractState, key: Pet) -> u64 " +#~ "{\n" +#~ " self.registration_time.read(key)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[derive(Copy, Drop, Serde, Hash)]\n" +#~ "struct Pet {\n" +#~ " name: felt252,\n" +#~ " age: u8,\n" +#~ " owner: felt252,\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::interface]\n" +#~ "trait IPetRegistry {\n" +#~ " fn register_pet(ref self: TContractState, key: Pet, timestamp: u64);\n" +#~ " fn get_registration_date(self: @TContractState, key: Pet) -> u64;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod PetRegistry {\n" +#~ " use hash::{HashStateTrait, Hash};\n" +#~ " use super::Pet;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " registration_time: LegacyMap::,\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl PetRegistry of super::IPetRegistry {\n" +#~ " fn register_pet(ref self: ContractState, key: Pet, timestamp: " +#~ "u64) {\n" +#~ " self.registration_time.write(key, timestamp);\n" +#~ " }\n" +#~ "\n" +#~ " fn get_registration_date(self: @ContractState, key: Pet) -> u64 " +#~ "{\n" +#~ " self.registration_time.read(key)\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# Hash Solidity Compatible" +#~ msgstr "# 兼容Hash Solidity" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISolidityHashExample {\n" +#~ " fn hash_data(ref self: TContractState, input_data: Span) -> " +#~ "u256;\n" +#~ "}\n" +#~ "\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SolidityHashExample {\n" +#~ " use keccak::{keccak_u256s_be_inputs};\n" +#~ " use array::Span;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SolidityHashExample of super::" +#~ "ISolidityHashExample {\n" +#~ " fn hash_data(ref self: ContractState, input_data: Span) -> " +#~ "u256 {\n" +#~ " let hashed = keccak_u256s_be_inputs(input_data);\n" +#~ "\n" +#~ " // Split the hashed value into two 128-bit segments\n" +#~ " let low: u128 = hashed.low;\n" +#~ " let high: u128 = hashed.high;\n" +#~ "\n" +#~ " // Reverse each 128-bit segment\n" +#~ " let reversed_low = integer::u128_byte_reverse(low);\n" +#~ " let reversed_high = integer::u128_byte_reverse(high);\n" +#~ "\n" +#~ " // Reverse merge the reversed segments back into a u256 " +#~ "value\n" +#~ " let compatible_hash = u256 { low: reversed_high, high: " +#~ "reversed_low };\n" +#~ "\n" +#~ " compatible_hash\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ISolidityHashExample {\n" +#~ " fn hash_data(ref self: TContractState, input_data: Span) -> " +#~ "u256;\n" +#~ "}\n" +#~ "\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod SolidityHashExample {\n" +#~ " use keccak::{keccak_u256s_be_inputs};\n" +#~ " use array::Span;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {}\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl SolidityHashExample of super::" +#~ "ISolidityHashExample {\n" +#~ " fn hash_data(ref self: ContractState, input_data: Span) -> " +#~ "u256 {\n" +#~ " let hashed = keccak_u256s_be_inputs(input_data);\n" +#~ "\n" +#~ " // Split the hashed value into two 128-bit segments\n" +#~ " let low: u128 = hashed.low;\n" +#~ " let high: u128 = hashed.high;\n" +#~ "\n" +#~ " // Reverse each 128-bit segment\n" +#~ " let reversed_low = integer::u128_byte_reverse(low);\n" +#~ " let reversed_high = integer::u128_byte_reverse(high);\n" +#~ "\n" +#~ " // Reverse merge the reversed segments back into a u256 " +#~ "value\n" +#~ " let compatible_hash = u256 { low: reversed_high, high: " +#~ "reversed_low };\n" +#~ "\n" +#~ " compatible_hash\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-11-21
" +#~ msgstr "
Last change: 2023-11-21
" + +#~ msgid "# Optimisations " +#~ msgstr "# 优化" + +#~ msgid "" +#~ "```rust\n" +#~ "trait StorePacking {\n" +#~ " fn pack(value: T) -> PackedT;\n" +#~ " fn unpack(value: PackedT) -> T;\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "trait StorePacking {\n" +#~ " fn pack(value: T) -> PackedT;\n" +#~ " fn unpack(value: PackedT) -> T;\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ITime {\n" +#~ " fn set(ref self: TContractState, value: TimeContract::Time);\n" +#~ " fn get(self: @TContractState) -> TimeContract::Time;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod TimeContract {\n" +#~ " use starknet::storage_access::StorePacking;\n" +#~ " use integer::{\n" +#~ " U8IntoFelt252, Felt252TryIntoU16, U16DivRem, u16_as_non_zero, " +#~ "U16IntoFelt252,\n" +#~ " Felt252TryIntoU8\n" +#~ " };\n" +#~ " use traits::{Into, TryInto, DivRem};\n" +#~ " use option::OptionTrait;\n" +#~ " use serde::Serde;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " time: Time\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Copy, Serde, Drop)]\n" +#~ " struct Time {\n" +#~ " hour: u8,\n" +#~ " minute: u8\n" +#~ " }\n" +#~ "\n" +#~ " impl TimePackable of StorePacking {\n" +#~ " fn pack(value: Time) -> felt252 {\n" +#~ " let msb: felt252 = 256 * value.hour.into();\n" +#~ " let lsb: felt252 = value.minute.into();\n" +#~ " return msb + lsb;\n" +#~ " }\n" +#~ " fn unpack(value: felt252) -> Time {\n" +#~ " let value: u16 = value.try_into().unwrap();\n" +#~ " let (q, r) = U16DivRem::div_rem(value, " +#~ "u16_as_non_zero(256));\n" +#~ " let hour: u8 = Into::::into(q).try_into()." +#~ "unwrap();\n" +#~ " let minute: u8 = Into::::into(r).try_into()." +#~ "unwrap();\n" +#~ " return Time { hour, minute };\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl TimeContract of super::ITime {\n" +#~ " fn set(ref self: ContractState, value: Time) {\n" +#~ " // This will call the pack method of the TimePackable trait\n" +#~ " // and store the resulting felt252\n" +#~ " self.time.write(value);\n" +#~ " }\n" +#~ " fn get(self: @ContractState) -> Time {\n" +#~ " // This will read the felt252 value from storage\n" +#~ " // and return the result of the unpack method of the " +#~ "TimePackable trait\n" +#~ " return self.time.read();\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait ITime {\n" +#~ " fn set(ref self: TContractState, value: TimeContract::Time);\n" +#~ " fn get(self: @TContractState) -> TimeContract::Time;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod TimeContract {\n" +#~ " use starknet::storage_access::StorePacking;\n" +#~ " use integer::{\n" +#~ " U8IntoFelt252, Felt252TryIntoU16, U16DivRem, u16_as_non_zero, " +#~ "U16IntoFelt252,\n" +#~ " Felt252TryIntoU8\n" +#~ " };\n" +#~ " use traits::{Into, TryInto, DivRem};\n" +#~ " use option::OptionTrait;\n" +#~ " use serde::Serde;\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " time: Time\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Copy, Serde, Drop)]\n" +#~ " struct Time {\n" +#~ " hour: u8,\n" +#~ " minute: u8\n" +#~ " }\n" +#~ "\n" +#~ " impl TimePackable of StorePacking {\n" +#~ " fn pack(value: Time) -> felt252 {\n" +#~ " let msb: felt252 = 256 * value.hour.into();\n" +#~ " let lsb: felt252 = value.minute.into();\n" +#~ " return msb + lsb;\n" +#~ " }\n" +#~ " fn unpack(value: felt252) -> Time {\n" +#~ " let value: u16 = value.try_into().unwrap();\n" +#~ " let (q, r) = U16DivRem::div_rem(value, " +#~ "u16_as_non_zero(256));\n" +#~ " let hour: u8 = Into::::into(q).try_into()." +#~ "unwrap();\n" +#~ " let minute: u8 = Into::::into(r).try_into()." +#~ "unwrap();\n" +#~ " return Time { hour, minute };\n" +#~ " }\n" +#~ " }\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl TimeContract of super::ITime {\n" +#~ " fn set(ref self: ContractState, value: Time) {\n" +#~ " // This will call the pack method of the TimePackable trait\n" +#~ " // and store the resulting felt252\n" +#~ " self.time.write(value);\n" +#~ " }\n" +#~ " fn get(self: @ContractState) -> Time {\n" +#~ " // This will read the felt252 value from storage\n" +#~ " // and return the result of the unpack method of the " +#~ "TimePackable trait\n" +#~ " return self.time.read();\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "# List" +#~ msgstr "# 列表" + +#~ msgid "" +#~ "```rust\n" +#~ "#[storage]\n" +#~ "stuct Storage {\n" +#~ " amounts: List\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[storage]\n" +#~ "stuct Storage {\n" +#~ " amounts: List\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "trait ListTrait {\n" +#~ " fn len(self: @List) -> u32;\n" +#~ " fn is_empty(self: @List) -> bool;\n" +#~ " fn append(ref self: List, value: T) -> u32;\n" +#~ " fn get(self: @List, index: u32) -> Option;\n" +#~ " fn set(ref self: List, index: u32, value: T);\n" +#~ " fn pop_front(ref self: List) -> Option;\n" +#~ " fn array(self: @List) -> Array;\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "trait ListTrait {\n" +#~ " fn len(self: @List) -> u32;\n" +#~ " fn is_empty(self: @List) -> bool;\n" +#~ " fn append(ref self: List, value: T) -> u32;\n" +#~ " fn get(self: @List, index: u32) -> Option;\n" +#~ " fn set(ref self: List, index: u32, value: T);\n" +#~ " fn pop_front(ref self: List) -> Option;\n" +#~ " fn array(self: @List) -> Array;\n" +#~ "}\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "let second = self.amounts.read()[1];\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "let second = self.amounts.read()[1];\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "let mut amounts = self.amounts.read();\n" +#~ "amounts.append(42);\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "let mut amounts = self.amounts.read();\n" +#~ "amounts.append(42);\n" +#~ "```" + +#~ msgid "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IListExample {\n" +#~ " fn add_in_amount(ref self: TContractState, number: u128);\n" +#~ " fn add_in_task(ref self: TContractState, description: felt252, " +#~ "status: felt252);\n" +#~ " fn is_empty_list(self: @TContractState) -> bool;\n" +#~ " fn list_length(self: @TContractState) -> u32;\n" +#~ " fn get_from_index(self: @TContractState, index: u32) -> u128;\n" +#~ " fn set_from_index(ref self: TContractState, index: u32, number: " +#~ "u128);\n" +#~ " fn pop_front_list(ref self: TContractState);\n" +#~ " fn array_conversion(self: @TContractState) -> Array;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ListExample {\n" +#~ " use alexandria_storage::list::{List, ListTrait};\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " amount: List,\n" +#~ " tasks: List\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Copy, Drop, Serde, starknet::Store)]\n" +#~ " struct Task {\n" +#~ " description: felt252,\n" +#~ " status: felt252\n" +#~ " }\n" +#~ "\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ListExample of super::IListExample {\n" +#~ " fn add_in_amount(ref self: ContractState, number: u128) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.append(number);\n" +#~ " }\n" +#~ "\n" +#~ " fn add_in_task(ref self: ContractState, description: felt252, " +#~ "status: felt252) {\n" +#~ " let new_task = Task { description: description, status: " +#~ "status };\n" +#~ " let mut current_tasks_list = self.tasks.read();\n" +#~ " current_tasks_list.append(new_task);\n" +#~ " }\n" +#~ "\n" +#~ " fn is_empty_list(self: @ContractState) -> bool {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.is_empty()\n" +#~ " }\n" +#~ "\n" +#~ " fn list_length(self: @ContractState) -> u32 {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.len()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_from_index(self: @ContractState, index: u32) -> u128 {\n" +#~ " self.amount.read()[index]\n" +#~ " }\n" +#~ "\n" +#~ " fn set_from_index(ref self: ContractState, index: u32, number: " +#~ "u128) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.set(index, number);\n" +#~ " }\n" +#~ "\n" +#~ " fn pop_front_list(ref self: ContractState) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.pop_front();\n" +#~ " }\n" +#~ "\n" +#~ " fn array_conversion(self: @ContractState) -> Array {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.array()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" +#~ msgstr "" +#~ "```rust\n" +#~ "#[starknet::interface]\n" +#~ "trait IListExample {\n" +#~ " fn add_in_amount(ref self: TContractState, number: u128);\n" +#~ " fn add_in_task(ref self: TContractState, description: felt252, " +#~ "status: felt252);\n" +#~ " fn is_empty_list(self: @TContractState) -> bool;\n" +#~ " fn list_length(self: @TContractState) -> u32;\n" +#~ " fn get_from_index(self: @TContractState, index: u32) -> u128;\n" +#~ " fn set_from_index(ref self: TContractState, index: u32, number: " +#~ "u128);\n" +#~ " fn pop_front_list(ref self: TContractState);\n" +#~ " fn array_conversion(self: @TContractState) -> Array;\n" +#~ "}\n" +#~ "\n" +#~ "#[starknet::contract]\n" +#~ "mod ListExample {\n" +#~ " use alexandria_storage::list::{List, ListTrait};\n" +#~ "\n" +#~ " #[storage]\n" +#~ " struct Storage {\n" +#~ " amount: List,\n" +#~ " tasks: List\n" +#~ " }\n" +#~ "\n" +#~ " #[derive(Copy, Drop, Serde, starknet::Store)]\n" +#~ " struct Task {\n" +#~ " description: felt252,\n" +#~ " status: felt252\n" +#~ " }\n" +#~ "\n" +#~ "\n" +#~ " #[abi(embed_v0)]\n" +#~ " impl ListExample of super::IListExample {\n" +#~ " fn add_in_amount(ref self: ContractState, number: u128) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.append(number);\n" +#~ " }\n" +#~ "\n" +#~ " fn add_in_task(ref self: ContractState, description: felt252, " +#~ "status: felt252) {\n" +#~ " let new_task = Task { description: description, status: " +#~ "status };\n" +#~ " let mut current_tasks_list = self.tasks.read();\n" +#~ " current_tasks_list.append(new_task);\n" +#~ " }\n" +#~ "\n" +#~ " fn is_empty_list(self: @ContractState) -> bool {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.is_empty()\n" +#~ " }\n" +#~ "\n" +#~ " fn list_length(self: @ContractState) -> u32 {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.len()\n" +#~ " }\n" +#~ "\n" +#~ " fn get_from_index(self: @ContractState, index: u32) -> u128 {\n" +#~ " self.amount.read()[index]\n" +#~ " }\n" +#~ "\n" +#~ " fn set_from_index(ref self: ContractState, index: u32, number: " +#~ "u128) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.set(index, number);\n" +#~ " }\n" +#~ "\n" +#~ " fn pop_front_list(ref self: ContractState) {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.pop_front();\n" +#~ " }\n" +#~ "\n" +#~ " fn array_conversion(self: @ContractState) -> Array {\n" +#~ " let mut current_amount_list = self.amount.read();\n" +#~ " current_amount_list.array()\n" +#~ " }\n" +#~ " }\n" +#~ "}\n" +#~ "```" + +#~ msgid "
Last change: 2023-11-27
" +#~ msgstr ""