diff --git a/.gitignore b/.gitignore
index 633f2680c..bb21c8017 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ node_modules
.env.local
.DS_Store
.docusaurus/*
+.vscode/*
out
build
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..271ed9427
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+ "grammarly.selectors": [
+ {
+ "language": "markdown",
+ "scheme": "file"
+ }
+ ]
+}
diff --git a/docs/tutorials.mdx b/docs/tutorials.mdx
index 16bfc8711..4f5120747 100644
--- a/docs/tutorials.mdx
+++ b/docs/tutorials.mdx
@@ -109,6 +109,14 @@ These tutorials are intended for developers who are familiar with Tezos and want
link="Start tutorial"
/>
+
+
.jsligo
+```
+
+> Alternative : You can use the Ligo compiler directly and it can be installed [here](https://ligolang.org/docs/intro/installation/?lang=jsligo)
+> You will have to compile the parameters and the storage yourself. Instead of using the taq command, use this one :
+>
+> ```bash
+> ligo compile contract ./contracts/.jsligo
+> ```
+
+---
+
+When you're ready, go to [Part 1: Programming errors](./security/part-1)
diff --git a/docs/tutorials/security/part-1.md b/docs/tutorials/security/part-1.md
new file mode 100644
index 000000000..067ea8377
--- /dev/null
+++ b/docs/tutorials/security/part-1.md
@@ -0,0 +1,239 @@
+---
+title: 'Part 1: Programming errors'
+authors: 'Benjamin Fuentes (Marigold)'
+last_update:
+ date: 11 January 2024
+---
+
+> Note : clone this [project](https://github.com/marigold-dev/training-security-1.git) for compiling and testing this tutorial
+
+Programming errors in web3 are mistakes or bugs that occur when writing smart contracts.
+
+## Bugs
+
+Writing Michelson code requires careful attention to detail and rigorous testing. If the code contains errors or inconsistencies, it may result in a failed transaction that consumes gas and storage fees. Therefore, it is advisable to use high-level languages that compile to Michelson, such as LIGO, and to verify the generated code before deploying it on the node.
+
+For example, LIGO uses the Option type to safely work with values that may or may not exist.
+If you subtract two tez or mutez variables, the result may be a negative number, which is not valid for the tez and mutez types.
+For this reason, LIGO requires you to wrap the result in an Option type, even if you are confident that the result is a positive number, as in this example:
+
+```ligolang
+option = 0mutez - 1mutez;
+```
+
+In the source code `.contracts/1-bugs.jsligo`, we have also a subtraction returning an optional
+
+```ligolang
+ match(store - delta) {
+```
+
+Compile the code and watch the generated Michelson code
+
+```bash
+taq init
+taq compile 1-bugs.jsligo
+more ./artifacts/1-bugs.tz
+```
+
+Line 6 of the compiled Michelson uses the `SUB_MUTEZ` instruction to subtract the two values.
+Next, it uses the `IF_NONE` instruction to check whether the subtraction instruction returned a result.
+If it did, it returns the number.
+LIGO is not compiling if you forget to manage the optional value and you return the result directly
+
+Run the code for the decrement of 0 by 1. 0 is the default value of the storage you can find on the **1-bugs.storageList.jsligo** file. 1 is the parameter passed on the simulation you can find on the **1-bugs.parameterList.jsligo** file.
+
+```bash
+taq simulate 1-bugs.tz --param 1-bugs.parameter.default_parameter.tz
+```
+
+All goes well as if there is an error on the subtraction, it is caught and returns an unchanged value
+
+Modify directly the Michelson file **./artifacts/1-bugs.tz** to not check the diff. Using **SUB** will not do specific checks for mutez and will not wrap it into an optional.
+
+```michelson
+{ parameter (or (unit %reset) (or (mutez %decrement) (mutez %increment))) ;
+ storage mutez ;
+ code { UNPAIR ;
+ IF_LEFT
+ { DROP 2 ; PUSH mutez 0 }
+ { IF_LEFT { SWAP ; SUB } { ADD } } ;
+ NIL operation ;
+ PAIR } }
+```
+
+Run it again
+
+```bash
+taq simulate 1-bugs.tz --param 1-bugs.parameter.default_parameter.tz
+```
+
+This time you have an error
+
+```logs
+Underflowing subtraction of 0 tez and 0.000001 tez
+```
+
+In this way, using the LIGO compiler instead of coding Michelson directly helps you avoid problems.
+
+→ **SOLUTION**: use the LIGO compiler to prevent runtime errors
+
+## Rounding issues
+
+Michelson does not support floats, so some rounding issues after a division can happen if it is not done carefully. This can cause a smart contract to halt in some situations.
+
+Let's take an example of the division of 101 by 4. In the file `2-rounding.jsligo` we have 2 users who would like to redeem the contract balance, with the user Alice receiving 3/4 and user Bob receiving 1/4. The contract calculates Alice's amount as the total minus 1/4 and Bob's amount as the total minus 3/4. Due to rounding, the total amount to withdraw from the contract can exceed the contract balance.
+
+Run the following code
+
+```bash
+taq compile 2-rounding.jsligo
+taq simulate 2-rounding.tz --param 2-rounding.parameter.default_parameter.tz
+```
+
+It will fail as the result will be negative, Alice will have 101-25=76 and Bob 101-(3\*25)=26, so the total to redeem is 102 greater than the initial 101
+
+```logs
+script reached FAILWITH instruction
+with "It is a failure !!!"
+```
+
+→ **SOLUTION**: Change the way to do the operation to not be influenced by the rounding effect. Calculate the first value and the rest for the second user
+
+Change the line for bob
+
+From
+
+```ligolang
+const bob = s - (3n * quotient);
+```
+
+To
+
+```ligolang
+const bob = s - alice;
+```
+
+Re-Compile-Run the code
+
+```bash
+taq compile 2-rounding.jsligo
+taq simulate 2-rounding.tz --param 2-rounding.parameter.default_parameter.tz
+```
+
+All good now =)
+
+## Unsecure bitwise operations
+
+A bitwise operation is a type of computation that operates on the individual bits of a binary number. A bitwise shift moves the bits of the operand to the left or right by a certain number of positions, filling the vacated bits with zeros.
+
+However, there is a caveat: if the shift amount is too large, it can cause an overflow, which means that some bits are lost or added beyond the expected size of the input. This can lead to unexpected results or errors in the execution of the contract in Michelson
+
+Run our two examples shifting to left and right
+
+```bash
+taq compile 3-bitwise.jsligo
+taq simulate 3-bitwise.tz --param 3-bitwise.parameter.shiftLeftOneNat.tz
+taq simulate 3-bitwise.tz --param 3-bitwise.parameter.shiftRight257times.tz
+```
+
+- The first example shifts 2n (0x0010) one time to the left, so it gives 4n (0x0100)
+- The second example shifts 2n (0x0010) 257 times to the right, as the limit is 256 shifts, it produces an error `unexpected arithmetic overflow`
+
+→ **SOLUTION**: To avoid this, one should always check the size of the input and the shift amount before applying the Bitwise instructions. Here you should check if the number of shifts is less than or equal to 256, otherwise, you raise an error
+
+## Sender vs Source confusion
+
+When a transaction is sent by a user, it can create other transactions on other smart contracts. Depending on the transaction, the original sender's address could be different from the direct sender of the transaction.
+
+```mermaid
+sequenceDiagram
+ Note left of User: I am the source of tx1 and tx2
+ User->>SmartContract1: transaction tx1
+ Note right of SmartContract1: I am the sender of tx2
+ SmartContract1->>SmartContract2: transaction tx2
+```
+
+In this example, transaction tx2 on SmartContract2 has :
+
+- The **User** as the source
+- The **SmartContract1** as the sender
+
+**Man-in-the-middle attack**: The victim contract is checking the source `Tezos.get_source()` to give access to an endpoint. If we have a phishing contract in the middle, it can call the endpoint while appearing to be the authorized caller. In this case, it can even grab some money in addition to the malicious action.
+
+Run the following test
+
+```bash
+taq test 4-manInTheMiddleTest.jsligo
+```
+
+```logs
+"Successfully hacked the victim and grab it money !!!"
+π All tests passed π
+```
+
+→ **SOLUTION**: Fix the code on the file `4-manInTheMiddleVictim.jsligo`, replacing `Tezos.get_source()` by `Tezos.get_sender()`
+
+Run it again
+
+```bash
+taq test 4-manInTheMiddleTest.jsligo
+```
+
+```logs
+Failwith: "You are not the admin to do this action"
+Trace:
+File "contracts/4-manInTheMiddleTest.jsligo", line 51, character 2 to line 59, character 3 ,
+File "contracts/4-manInTheMiddleTest.jsligo", line 51, character 2 to line 59, character 3 ,
+File "contracts/4-manInTheMiddleTest.jsligo", line 69, characters 17-24
+
+===
+βββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββ
+β Contract β Test Results β
+βββββββββββββββββββββββββββββββΌβββββββββββββββββββββββ€
+β 4-manInTheMiddleTest.jsligo β Some tests failed :( β
+βββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββ
+```
+
+> Note : On some specific cases it is important to authorize an intermediary contract to communicate with our contract. We should not always check the source as the default behavior for rejection
+
+## Library updates
+
+This is a DEVOPS issue. If a CI recompiles the code before deploying a new version and there are dependencies to fetch, maybe the new behavior will not be compatible with your code logic and bring new security flaws
+
+→ **SOLUTION**: Do more unit tests and publish CI test reports
+
+## Private data
+
+One of the most important security considerations for smart contract developers is to avoid storing any sensitive or confidential information on the contract storage. This is because the contract storage is public and immutable, meaning that anyone can read its contents and it cannot be erased or modified. Therefore, any secret value, such as a private key, a password, or a personal identification number, should never be stored on the contract storage. Doing so would expose the secret value to potential attackers and compromise the security and privacy of the contract and its users.
+
+→ **SOLUTION**: Instead, secret values should be stored off-chain, such as in a secure database or a hardware wallet, and only communicated to the contract when necessary using encryption with Commit&Reveal pattern or zero-knowledge proofs.
+
+## Predictable information used as a random value
+
+Due to the deterministic nature of blockchain execution, it is not possible to generate random numbers or values within a smart contract. This means that any logic that relies on randomness, such as games, lotteries, or auctions, cannot be implemented securely and fairly on a blockchain. Therefore, smart contract developers need to find alternative ways to introduce randomness into their applications, such as using external sources of randomness (oracles) or cryptographic techniques (commit-reveal schemes).
+
+→ **SOLUTION** :
+
+- Use block timestamp: This approach has a low cost but also a high risk of being compromised, as the time parameter is too coarse and can be easily estimated based on the average block time
+- use contract origination address: This approach has a low cost but also a high risk of being compromised, as it is composed of the hash of the operation concatenated with an origination index
+- Multi-participant random seed: One possible way to generate a multi-participant random seed is to ask each participant to submit a random number in a secure and verifiable way. This can be done using a commit-reveal scheme, where each participant first commits to their number by sending a hash of it, and then reveals it later by sending the actual number. The hash function ensures that the participants cannot change their numbers after committing, and the reveal phase allows everyone to verify that the numbers match the hashes. The final seed can be computed by combining all the revealed numbers using some deterministic function, such as XOR or modular addition.
+ However, this method has some drawbacks, such as requiring two rounds of communication and being vulnerable to a locked situation, where some participants do not reveal their numbers and prevent the seed from being generated. To avoid this, there should be some incentive mechanism or timeout mechanism to ensure that everyone reveals their numbers in time, or else they are penalized or excluded from the seed generation.
+- Good randomness oracle: Creating a good off-chain random Oracle is not easy, as it requires a way to prove that the numbers are indeed random and not manipulated by anyone. One possible solution is to use a verifiable random function (VRF), which is a cryptographic algorithm that generates a random output from an input and a secret key. It produces a proof that the output was correctly computed. The proof can be verified by anyone who knows the input and the public key, but not the secret key. Chainlink is a decentralized network of Oracles that offers a VRF-based randomness Oracle for smart contracts. It claims to be one of the few, if not the only reasonably good available randomness Oracle in the market. However, it has some limitations, such as being only compatible with Ethereum and not with Tezos, which is another popular smart contract platform. Moreover, it still relies on the trustworthiness of a third party, namely the Chainlink node operators that hold the secret keys and generate the random numbers and proofs.
+
+## Blocked state
+
+One of the possible scenarios in a blockchain smart contract is to have a blocked state, where the contract execution is paused until a certain condition is met by one of the participants. For example, a contract that implements a simple escrow service might have a blocked state where the seller has to confirm the delivery of the goods before the buyer can release the payment. This way, the contract ensures that both parties are satisfied with the transaction and no one can cheat or withdraw from the agreement.
+
+Another example is in this Shifumi game (https://github.com/marigold-dev/training-dapp-shifumi), the contract can be blocked if one of the players does not reveal their choice within 10 minutes. In this case, the other player can claim a resolution and win the game by calling a function on the contract. This way, the contract is not stuck indefinitely and the honest player is rewarded.
+
+→ **SOLUTION** :
+
+- Define clear and objective rules for entering and exiting the blocked state, as well as for handling exceptions and disputes.
+- Use timeouts or deadlines to limit the duration of the blocked state and avoid indefinite waiting or deadlock situations.
+- Implement incentives or penalties to encourage or discourage certain behaviors or actions by the participants during the blocked state.
+- Provide feedback and notifications to the participants about the status and progress of the contract during the blocked state.
+- Use external oracles or trusted third parties to verify or arbitrate the condition that triggers the blocked state, if necessary.
+
+---
+
+Go to [Part 2: Leaks](./part-2).
diff --git a/docs/tutorials/security/part-2.md b/docs/tutorials/security/part-2.md
new file mode 100644
index 000000000..3b0ac7d7f
--- /dev/null
+++ b/docs/tutorials/security/part-2.md
@@ -0,0 +1,267 @@
+---
+title: 'Part 2: Leaks'
+authors: 'Benjamin Fuentes'
+last_update:
+ date: 11 January 2024
+---
+
+> Note : clone this [project](https://github.com/marigold-dev/training-security-2.git) for compiling and testing this tutorial
+
+## Replay attack
+
+A replay attack on a smart contract is a type of security vulnerability that allows an attacker to reuse a signed valid transaction multiple times. We saw in the previous chapter how to do offchain replay attacks, but it is possible to do also onchain replay attacks.
+Besides, Tezos prevents this kind of vulnerability, it is possible to write a code that does this attack sending the same operation several times for execution.
+
+Compile and simulate the replay attack :
+
+```bash
+taq init
+taq compile 1-replay.jsligo
+taq simulate 1-replay.tz --param=1-replay.parameter.parameter.tz
+```
+
+The simulation will tell you that several internal transactions will be executed.
+But if you deploy the code and try to execute it :
+
+```bash
+taq deploy 1-replay.tz --mutez 1000 -e testing
+
+taq transfer KT1VMt7t4CboRP6jYBUdBQowHb4NR1UtmDrz -e testing
+```
+
+Then, the Tezos will detect the flaw
+
+```logs
+ "message": "(transaction) proto.017-PtNairob.internal_operation_replay"
+```
+
+## Memory overflow
+
+Memory overflow is a kind of attack that overloads the memory of a smart contract resulting in making this contract unusable. Even simply loading the data into memory and deserializing it at the beginning of the call could use so much gas that any call to the contract would fail. All the funds would be forever locked into the contract.
+
+Here is the list of dangerous types to use carefully :
+
+- Integers and nats: as they can be increased to an arbitrarily large value
+- Strings: as there is no limit on their lengths
+- Lists, sets, maps: that can contain an arbitrary number of items
+
+→ **SOLUTION**:
+
+- Ask the user to pay a minimum tez for each call
+- Set a threshold limit
+- Store data on a big_map
+- Avoid unnecessary onchain computation that can be done offchain. Ex: do not loop onchain and just update a part of a map
+
+Example with the current FA1.2 implementation: https://inference.ag/blog/2023-10-09-FA12_spenders/
+
+You can have a look at the LIGO implementation of fa1.2 on the Ligo registry [here](https://packages.ligolang.org/package/ligo_fa1.2)
+
+The code follows the standard but you can see that the [Allowance type is a map](https://github.com/frankhillard/ligoFA12/blob/main/lib/asset/allowance.mligo#L3C8-L3C8). It would have been better to change the Standard and use a `big_map` instead of a `map`. If you implement the Standard differently, then your smart contract storage definition and entrypoint signatures will not match anymore and will not be supported by other platforms
+
+## Re-entrancy
+
+These attacks allow an attacker to repeatedly call a contract function in a way that drains the contractβs resources, leading to a denial of service (DoS) attack
+
+One of the most well-known examples of a re-entrancy attack occurred in 2016 when an attacker exploited a vulnerability in the DAO (Decentralized Autonomous Organization) contract on the Ethereum blockchain. But this popular hack is still actively used :
+
+- Uniswap/Lendf.Me hacks (April 2020) β $25 mln, attacked by a hacker using a re-entrancy.
+- The BurgerSwap hack (May 2021) β $7.2 mln, because of a fake token contract and a re-entrancy exploit.
+- The SURGEBNB hack (August 2021) β $4 mln, seems to be a re-entrancy-based price manipulation attack.
+- CREAM FINANCE hack (August 2021) β $18.8 mln, re-entrancy vulnerability allowed the exploiter for the second borrow.
+- Siren protocol hack (September 2021) β $3.5 mln, AMM pools were exploited through re-entrancy attack.
+
+This kind of attack is quite simple to put in place with Solidity because of the way it works.
+
+Consider this scenario :
+
+```mermaid
+sequenceDiagram
+ User->>MaliciousContract: deposit funds
+ MaliciousContract->>LedgerContract: deposit funds
+ User->>MaliciousContract: call withdraw
+ MaliciousContract->>LedgerContract: call withdraw
+ Note right of LedgerContract: checkBalance
+ Note right of LedgerContract: sendFunds
+ LedgerContract->>MaliciousContract: sendFunds operation
+ Note right of MaliciousContract: loop calling withdraw ... x times
+ MaliciousContract->>LedgerContract: call withdraw
+ LedgerContract->>MaliciousContract: sendFunds operation ... x times
+ Note right of LedgerContract: ... Once finish ... UpdateBalance
+```
+
+Why this scenario is possible on Solidity?
+On Solidity, the operation will call directly the smart contract, stopping the execution, calling a synchronous execution and resuming the flow. If someone calls several times and very quickly the withdraw operation, as the state is not updated yet, the call will succeed and drain more than the developer expected.
+
+Why this scenario is not possible on Tezos?
+On Tezos, the first transaction will update the state and will execute a list of operations at the end of execution. Next executions will encounter an updated state
+
+Let's implement a more complex scenario where the OfferContract and LedgerContract are separated. The OfferContract will naively send the money back to MaliciousContract because it relies on the **not yet modified** state of the LedgerContract. There are two operations and the modification of the state will come in second position.
+
+```mermaid
+sequenceDiagram
+ User->>MaliciousContract: deposit cookies
+ MaliciousContract->>LedgerContract: deposit cookies
+ User->>MaliciousContract: sell cookies
+ MaliciousContract->>OfferContract: sell cookies
+ Note right of OfferContract: checkBalance
+ OfferContract->>LedgerContract: call hasCookies view
+ Note right of OfferContract: prepare post operations (sendFund + changeOwner)
+ OfferContract->>MaliciousContract: sendFund
+ Note right of MaliciousContract: while receiving fund on default entrypoint will loop on selling cookies
+ MaliciousContract->>OfferContract: sell cookies
+ Note right of OfferContract: checkBalance
+ OfferContract->>LedgerContract: call hasCookies view
+ Note right of OfferContract: prepare post operations (sendFund + changeOwner)
+ OfferContract->>MaliciousContract: sendFund
+ MaliciousContract->>OfferContract: sell cookies
+ Note right of OfferContract: checkBalance
+ OfferContract->>LedgerContract: call hasCookies view
+ Note right of OfferContract: prepare post operations (sendFund + changeOwner)
+ OfferContract->>MaliciousContract: sendFund
+ OfferContract->>LedgerContract: call changeOwner
+```
+
+The issue here is clearly that we send money without updating the state first
+
+→ **SOLUTION** :
+
+- Mutex safeguard: To prevent the contract from generating multiple internal operations, we can add a Mutual Exclusive semaphore Boolean named `isRunning` that is true when an operation is running. This variable locks the contract while the full transaction flow runs.
+
+ 1. Check the isRunning is false
+ 2. Set isRunning to true
+ 3. Do logic code ...
+ 4. Create a last operation transaction to reset the boolean to false
+
+- Check-and-send pattern: Principle of separating state changes from external contract interactions. First, update the contractβs state, then interact with other contracts
+
+Compile/Run the hack test first
+
+```bash
+taq test 3-reentrancyTest.jsligo
+```
+
+The logs seem to be fine, but it is hard to guess the internal transactions and to separate the fees from the hack on the attacker's balance
+
+```logs
+βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββ
+β Contract β Test Results β
+βββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββ€
+β 3-reentrancyTest.jsligo β "ledgerContract" β
+β β KT1LQyTHEZeaecRj7hWgkzPEBD6vMEKXYzoo(None) β
+β β "offerContract" β
+β β KT1M4nPCej4va4Q2iMPX2FKt8xLw5cfGjBv9(None) β
+β β "maliciousContract" β
+β β KT1B7RgF6j7UpAybpdfxhLCp7hf41pNFcxyS(None) β
+β β "admin initialize cookies to malicious KT1" β
+β β Success (1299n) β
+β β "COOKIES OWNERS" β
+β β {KT1B7RgF6j7UpAybpdfxhLCp7hf41pNFcxyS} β
+β β "BALANCE OF SENDER" β
+β β 3799985579750mutez β
+β β Success (1798n) β
+β β "AFTER RUN - BALANCE OF SENDER" β
+β β 3799984579749mutez β
+β β {KT1LQyTHEZeaecRj7hWgkzPEBD6vMEKXYzoo} β
+β β "END RUN - BALANCE OF SENDER" β
+β β 3799984579749mutez β
+β β {KT1LQyTHEZeaecRj7hWgkzPEBD6vMEKXYzoo} β
+β β Everything at the top-level was executed. β
+β β - testReentrancy exited with value true. β
+β β β
+β β π All tests passed π β
+βββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββ
+```
+
+To have a better visualization of the hack, the contract should be deployed
+
+Compile the first contract, the Ledger contract, and deploy it
+
+```bash
+taq compile 3-reentrancyLedgerContract.jsligo
+taq deploy 3-reentrancyLedgerContract.tz -e testing
+```
+
+Copy the contract address, in my case KT1BJZfhC459WqCVJzPmu3vJSWFFkvyi9k1u, and paste it on the file `3-reentrancyOfferContract.storageList.jsligo` with your value
+
+Compile/deploy the second contract, the Offer contract, putting some money on the contract for the thieves
+
+```bash
+taq compile 3-reentrancyOfferContract.jsligo
+taq deploy 3-reentrancyOfferContract.tz -e testing --mutez 10000000
+```
+
+Copy the contract address, in my case KT1CHJgXEdBPktNNPGTDaL8XEAzJV9fjSkrZ, and paste it on the file `3-reentrancyMaliciousContract.storageList.jsligo` with your value
+
+Compile/deploy the last contract, the Malicious contract which will loop and steal the funds of the Offer contract
+
+```bash
+taq compile 3-reentrancyMaliciousContract.jsligo
+taq deploy 3-reentrancyMaliciousContract.tz -e testing
+```
+
+Copy the contract address, in my case KT1NKLZE9HkGJxjopowLqxA4pswutgMrrXyE, and initialize the Ledger contract as the Malicious contract as some cookies on its storage. Paste the value in the file `3-reentrancyLedgerContract.parameterList.jsligo`
+
+Once done, compile the Ledger contracts and call with this parameter
+
+```bash
+taq compile 3-reentrancyLedgerContract.jsligo
+taq call 3-reentrancyLedgerContract --param 3-reentrancyLedgerContract.parameter.default_parameter.tz -e testing
+```
+
+Context is ready:
+
+- The Malicious contract has cookies on the Ledger contract
+- All deployed contract points to the correct addresses
+
+Now the Malicious contract will try to steal funds from the Offer contract, run the command to start the attack the transaction flow
+
+```bash
+octez-client transfer 0 from alice to KT1NKLZE9HkGJxjopowLqxA4pswutgMrrXyE --entrypoint attack --arg 'Unit' --burn-cap 1
+```
+
+Here you can see the result on the Ghostnet: https://ghostnet.tzkt.io/KT1NKLZE9HkGJxjopowLqxA4pswutgMrrXyE/operations/
+
+3 refunds will be emitted instead of one
+
+→ **SOLUTION**: on the `3-reentrancyOfferContract.jsligo` file, line 34, swap the order of operation execution
+
+from
+
+```
+return [list([opTx, opChangeOwner]), s];
+```
+
+to
+
+```
+return [list([opChangeOwner,opTx]), s];
+```
+
+and rerun the scenario from scratch redeploying the contracts. It should be impossible to run the attack, as the transaction will fail
+
+```logs
+"message":"user do not have cookies"
+```
+
+- Authorize withdraw transfer only to a user account: As User wallet cannot do callback loops, it solves the issue but this solution is not always feasible and limiting. To check if an address is implicit, the Tezos.get_sender and the Tezos.get_source are always equal.
+
+- Audit External Contract calls: This is very hard to check, for example on withdrawal for a token transfer, any contract can receive funds.
+
+- Call third-party security experts or employ automated security tools: If you are not sure about your code, they will identify weaknesses and validate the contractβs security measures.
+
+## Overflow
+
+Manipulating arithmetic operations can lead to overflows and underflows
+
+- On Solidity: SafeMath is a library in Solidity that was designed to provide safe mathematical operations. It prevents overflow and underflow errors when working with unsigned integers (uint), which can lead to unexpected behavior in smart contracts. However, since Solidity v0.8.0, this library has been made obsolete as the language itself starts to include internal checking.
+
+- On LIGO: For the nat, int, and timestamp types, the Michelson interpreter uses arbitrary-precision arithmetic provided by the [OCaml Zarith library](https://github.com/ocaml/Zarith). It means that their size is only limited by gas or storage limits. You can store huge numbers in a contract without reaching the limit. However, in LIGO, an overflow will cause the contract to fail.
+
+→ **SOLUTION** :
+
+- For large tez values, do operation on int or nat as it has larger memory values
+- There is no other solution than using types with larger values as the default behavior is to reject the transaction in case of overflow
+
+> Do not confuse with [Ligo MathLib library](https://packages.ligolang.org/package/@ligo/math-lib) providing manipulation of floats and rationals instead of using basic types.
+
+Go to [Part 3: User trust & management](./part-3).
diff --git a/docs/tutorials/security/part-3.md b/docs/tutorials/security/part-3.md
new file mode 100644
index 000000000..8b09f0d65
--- /dev/null
+++ b/docs/tutorials/security/part-3.md
@@ -0,0 +1,63 @@
+---
+title: 'Part 3: User trust & management'
+authors: 'Benjamin Fuentes (Marigold)'
+last_update:
+ date: 11 January 2024
+---
+
+## Governance
+
+A decentralized system is not enough to ensure the security and efficiency of a blockchain network. It also requires a robust governance model that can handle conflicts, upgrades, and innovations. Moreover, the distribution of the native token that powers the network should be fair and balanced, avoiding the concentration of power and wealth among a few actors. If these conditions are not met, the decentralized system may suffer from instability, stagnation, or manipulation. Therefore, it is important to design and implement a governance model and a token distribution strategy that align with the goals and values of the network and its users
+
+One of the challenges of designing and deploying a smart contract is to define the roles and permissions of the different parties involved in the execution of the contract. The question is who can do what?
+
+- Who can create, modify, or terminate the contract?
+ - Creation: A smart contract is generally deployed by a DevOps person or a CI pipeline. Apart from knowing the creator's address and the fees he paid, there is no critical event that can appear at this moment. The only hack here would be to impersonate another company's smart contract, as discussed in the introduction of this training
+ - Update: By design, a smart contract code cannot be modified because it is immutable. However, lambdas are an exception, as described in the next section.
+ - Deletion: By design, a smart contract cannot be deleted because the code is stored on a block forever and can be called/executed at any time. The only way to terminate a smart contract would be to programmatically have a boolean to enable/disable all entrypoints
+- Who can invoke, monitor, or verify the contract functions?
+ - Invocation: This depends on the role-based access set on each entrypoints. By default, all annotated `@entry` functions are exposed and are callable.
+ → **SOLUTION**: Be very careful about who has to right the call each of your entrypoints, one of the best practices for writing secure and reliable code is to always check the validity and trustworthiness of the inputs and outputs of your functions. This means that you should **verify either the sender or the source** every time at the beginning of your function to act as a guard against malicious or erroneous data
+ [Look here for another way of doing RBAC with Tezos tickets](https://github.com/marigold-dev/training-dapp-3)
+ - Monitoring: Anyone can do this. The most famous ones are indexers, but there is no professional alerting system so far.
+ - Verification: By design, everyone can verify the code. Sometimes the code is audited and a report is available.
+ → **SOLUTION**: Read the audit if available or verify the code yourself. However, the code deployed is in Michelson and the reverse engineering is not easy. Tools are missing for now to reverse engineer contracts, nevertheless if the contract is TZIP16-compliant it can refer to the Ligo source code, so you can recompile and compare the outputs
+- Who can resolve disputes or enforce penalties in case of contract violations?
+ If the contract itself does not contain a function to resolve it, no resolution can happen onchain.
+ → **SOLUTION**: Use onchain dispute if available, or off-chain dispute but this latter introduces additional complexities such as Know Your Customer (KYC) regulations and legal considerations. KYC regulations require businesses to verify the identity of their clients. This can be difficult in the context of blockchain transactions, which are often pseudonymous. Legal considerations can also be complex, especially in cross-border transactions where different jurisdictions may have different laws.
+
+## Lambda, mutable code and dynamic entrypoints
+
+A smart contract is immutable but not the storage that represents the mutable state.
+A common way to change the behavior of a smart contract is to store some mutable code inside its storage and then execute it from the smart contract itself.
+
+This feature presents a **high risk and breaks the trust** you can have in the execution of the contract. If the governance is not clear and transparent, an administrator can potentially push any function and drain your funds from this contract. It is recommended to read carefully the code to see which kind of action can be done through this lambda. A lambda can access the contract's state and call other functions.
+For example, if the lambda is called in a function to update a static data configuration that has few impacts, then it is not necessarily dangerous. But if the lambda can create an operation that can be executed or is returning false information to fool the user over a transaction, then it is a red flag
+
+> Other techniques exist to update a dApp, like the proxy pattern. It does not change the code of the smart contract, but deployed a new version of it and a proxy contract will redirect the user transaction to this new contract. The risk is located on the proxy contract. If this contract is hacked and badly protected, anyone can deploy a malicious contract and redirect to it
+
+For an example of upgrading smart contracts with lambdas and proxies, see [Create your minimum dapp on Tezos](../dapp).
+
+## (Trustable) oracles
+
+Blockchain oracles are third-party services that provide smart contracts with external information. They serve as bridges between blockchains and the outside world, allowing smart contracts to access off-chain data. Oracles verify, query, and authenticate external data sources, and transmit any valuable data.
+
+An Oracle is made of two parts:
+
+- Offchain: the data collector who pushes it to the onchain contract
+- Onchain: the contract stores the data on its storage and exposes it to other contracts. Generally, a call for information involves monetization and so, some fees apply.
+
+Who controls the oracle?
+It can be a single company or person. So they can manipulate the data, being hacked or the service can go down and block the full flow of execution.
+
+→ **SOLUTION** :
+
+- Use many decentralized Oracles :
+ - To avoid collusion. More actors equals less centralized power.
+ - To avoid one single oracle from affecting the volatility. Several sources average is better than relying on only one source, especially on CEX/DEX with few volumes
+- Always use oracles that provide timestamps: each data should have a validity date associated otherwise it is almost impossible to apply to correct data and verify afterward
+
+There are some providers on the market claiming to have decentralized Oracles or ZK execution :
+
+- [Chainlink](https://chain.link/whitepaper)
+- [Acurast](https://docs.acurast.com/acurast-protocol/architecture/architecture/)
diff --git a/sidebars.js b/sidebars.js
index cf51c0d4f..8b47164ba 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -358,6 +358,19 @@ const sidebars = {
'tutorials/build-an-nft-marketplace/part-4',
],
},
+ {
+ type: 'category',
+ label: 'Learn and play with security',
+ link: {
+ type: 'doc',
+ id: 'tutorials/security',
+ },
+ items: [
+ 'tutorials/security/part-1',
+ 'tutorials/security/part-2',
+ 'tutorials/security/part-3',
+ ],
+ },
{
type: 'category',
label: 'Create a mobile game',