Read Only Reentrancy | Hack Solidity (0.8)

Smart Contract Programmer
30 Oct 202219:55

Summary

TLDRThis transcript details a step-by-step process of executing a read-only reentrancy attack on a smart contract, specifically targeting the Curve Finance pool. The speaker explains how to simulate the attack using Foundry, a framework for Ethereum development. The attack involves manipulating the contract's liquidity functions to exploit the timing discrepancy between function calls, allowing for an increased return on rewards based on an artificially inflated virtual price of the liquidity provider tokens.

Takeaways

  • 🔍 A re-entrancy hack involves a malicious contract calling into a target contract, which then calls back into the original contract, creating a loop.
  • 📌 In a read-only re-entrancy scenario, the hack contract first interacts with a 'date contract' before fully completing its initial call to the target contract.
  • 🚀 The script provides a step-by-step guide on how to simulate a read-only re-entrancy attack using Foundry on the main network without actually hacking a contract.
  • đŸ› ïž The example uses the Curve pool as a target for the simulated read-only re-entrancy attack.
  • 📝 The script outlines the installation and initialization process of Foundry, including the necessary commands.
  • 🔑 The hack contract is created with specific Solidity code, including the interface for the Curve contract and the ERC20 interface.
  • 🔄 The attack simulates adding liquidity to the Curve pool, logging the virtual price, and then removing liquidity to trigger the re-entrancy.
  • 📊 The script demonstrates how the virtual price can appear higher during the removal of liquidity due to the timing of the read-only re-entrancy.
  • 🎯 The exploit involves staking LP tokens into a target contract that rewards based on the virtual price returned by the Curve pool's 'get virtual price' function.
  • 📈 The script shows that by exploiting the timing of the read-only re-entrancy, more rewards can be obtained than in a normal transaction flow.
  • 📋 The script includes a detailed explanation of the Solidity code used for the hack contract and the target contract, including function definitions and interactions.
  • 🧐 The script concludes by showing the results of the simulated attack, highlighting the difference in rewards obtained before and during the liquidation process.

Q & A

  • What is a re-entrancy hack?

    -A re-entrancy hack is a type of smart contract exploit where a malicious contract calls into a target contract and then the target contract calls back into the original malicious contract. This back-and-forth interaction can be exploited to manipulate the state of the target contract or extract additional benefits from it.

  • How does a read-only re-entrancy attack differ from a regular re-entrancy attack?

    -A read-only re-entrancy attack is more complex than a regular re-entrancy attack. In a regular re-entrancy attack, the malicious contract can modify the state of the target contract during the callback. However, in a read-only re-entrancy attack, the malicious contract cannot modify the state of the target contract during the callback, but it can still exploit the timing of the function calls to gain an advantage.

  • What is the purpose of the 'hack' contract in the provided script?

    -The 'hack' contract in the script is designed to simulate a read-only re-entrancy attack on the Curve pool. It is used to demonstrate how an attacker might exploit a vulnerability in the Curve pool's smart contract to gain additional benefits while the 'remove liquidity' function is being executed.

  • What are the key functions of the Curve pool contract that are being exploited in the script?

    -The key functions of the Curve pool contract being exploited are 'getVirtualPrice', 'addLiquidity', and 'removeLiquidity'. The 'getVirtualPrice' function returns the value of the shares, 'addLiquidity' is used to add tokens to the pool, and 'removeLiquidity' is used to withdraw tokens from the pool.

  • How does the 'hack' contract manipulate the timing of function calls to execute a read-only re-entrancy attack?

    -The 'hack' contract first adds liquidity to the Curve pool and then logs the value of the shares using 'getVirtualPrice'. It then initiates the 'removeLiquidity' function, which triggers the attack. During the execution of 'removeLiquidity', before it finishes, the 'hack' contract sends a transaction back to itself, which triggers the 'receive' function. Inside this 'receive' function, the 'hack' contract can call 'getVirtualPrice' again, this time while 'removeLiquidity' is still executing, and exploit the temporarily inflated share value to gain more rewards.

  • What is the role of the 'Target' contract in the script?

    -The 'Target' contract is a hypothetical contract that is used to demonstrate how a read-only re-entrancy attack can be exploited. It has functions to stake LP tokens, unstake LP tokens, and get rewards based on the value returned by 'getVirtualPrice'. The 'hack' contract interacts with this 'Target' contract to show how an attacker could manipulate the timing of function calls to get more rewards than they would under normal circumstances.

  • How does the 'hack' contract ensure it gets the correct amount of rewards during the attack?

    -The 'hack' contract ensures it gets the correct amount of rewards by staking LP tokens into the 'Target' contract before initiating the 'removeLiquidity' function. Once 'removeLiquidity' is called and the 'receive' function is triggered, the 'hack' contract calls the 'getReward' function on the 'Target' contract. The rewards are calculated based on the temporarily inflated 'getVirtualPrice' value, which is higher than it would be if the 'removeLiquidity' function had completed execution.

  • What is the significance of the 'receive' function in the 'hack' contract?

    -The 'receive' function in the 'hack' contract is crucial for the read-only re-entrancy attack. It is the entry point for the transaction sent back to the 'hack' contract during the execution of 'removeLiquidity'. This function allows the 'hack' contract to execute additional code while the 'removeLiquidity' function is still running, enabling the exploit to take advantage of the inflated share value.

  • How does the script demonstrate the difference in rewards before and after the read-only re-entrancy attack?

    -The script demonstrates the difference in rewards by showing the 'getVirtualPrice' value before and during the 'removeLiquidity' function execution. The 'getVirtualPrice' value is higher during the execution because liquidity is being removed, which temporarily inflates the share value. The script then compares the rewards calculated using this inflated value (inside the 'receive' function) with the rewards calculated after the 'removeLiquidity' function has completed, showing that more rewards are obtained during the attack.

  • What is the purpose of the 'setup' function in the 'hack' contract?

    -The 'setup' function in the 'hack' contract is used to stake LP tokens into the 'Target' contract before initiating the attack. This is a necessary step to ensure that the 'hack' contract has tokens in the 'Target' contract to calculate rewards from, which is a key part of the read-only re-entrancy exploit.

  • What is the role of the 'Forge' tool in the script?

    -The 'Forge' tool is used to compile and test the smart contracts written in the script. It is a development utility that helps in building, deploying, and interacting with smart contracts on the Ethereum blockchain.

  • How does the script ensure that the exploit is executed on the main network?

    -The script uses a fork of the main network to execute the exploit. This allows the developer to test the attack without actually interacting with the real main network, thus preventing any real-world consequences while still simulating a realistic environment.

Outlines

00:00

🔍 Understanding Re-Entrancy Hacks

This paragraph introduces the concept of re-entrancy hacks, particularly focusing on how a malicious contract can manipulate a Target contract's state by making recursive calls. It explains the process of a re-entrancy attack, where the hack contract first interacts with the Target, then the Target calls back into the hack contract. The example given involves a read-only re-entrancy attack simulation using Foundry, a development framework for Ethereum. The speaker guides through the installation of Foundry and the initialization of a project, setting the stage for a practical demonstration of a read-only re-entrancy attack on a hypothetical smart contract.

05:03

📝 Coding the Re-Entrancy Attack

The speaker delves into the technical details of executing a read-only re-entrancy attack by coding a 'hack' contract. The process involves setting up the contract with specific addresses, defining functions for adding and removing liquidity from a pool, and exploiting the timing of function calls to manipulate the 'get virtual price' function. The speaker outlines the steps of adding liquidity to a pool, logging the virtual price, and then removing liquidity to trigger the attack. The explanation includes the preparation of necessary data structures and the intricate dance of function calls that lead to the exploit.

10:03

🎯 Targeting a Contract for Exploitation

This section describes the creation of a 'Target' contract that simulates a contract vulnerable to read-only re-entrancy attacks. The speaker outlines the functionalities of the Target contract, which includes staking and unstaking LP tokens and a reward system based on the virtual price. The speaker emphasizes the importance of the virtual price in the exploit, as it is used to calculate rewards. The Target contract's code is detailed, including the logic for stake, unstake, and get rewards functions, which are crucial for the exploit to work.

15:05

🚀 Executing the Exploit

The speaker concludes the video script by integrating the previously discussed concepts into a full-fledged exploit. The hack contract is updated to include the Target contract, and a setup function is added to stake LP tokens into the Target. The main 'poem' function is then used to trigger the re-entrancy attack, demonstrating how the exploit can yield more rewards than legitimate interactions with the Target contract. The speaker runs a test on the main network to validate the exploit, showing the difference in rewards before and during the removal of liquidity, thus illustrating the impact of read-only re-entrancy attacks on smart contracts.

Mindmap

Keywords

💡Re-entrancy Hack

A re-entrancy hack is a type of blockchain exploit where a malicious contract calls another contract and then calls back into the caller before the original call has finished executing. This allows the malicious contract to manipulate the state of the target contract. In the video, the hack contract calls the Target contract, which then calls back into the hack contract, exploiting the re-entrancy vulnerability.

💡Target Contract

In the context of the video, the Target Contract refers to the smart contract that is being exploited by the hack contract. It is the contract that the hacker is trying to manipulate by taking advantage of re-entrancy vulnerabilities.

💡Call Back

A call back in programming is a mechanism where a function or routine is called as a response to a particular event. In the context of the video, the call back refers to the Target contract calling back into the hack contract during a re-entrancy attack.

💡Read-Only Reentrancy

Read-Only Reentrancy is a more complex form of re-entrancy attack where the hacker's contract reads state from another contract while the first call is still executing, potentially leading to manipulation of the state based on outdated or partial information. This type of attack is harder to detect and defend against compared to traditional re-entrancy attacks.

💡Solidity

Solidity is a programming language specifically designed for writing smart contracts on the Ethereum blockchain. It is a contract-oriented, high-level programming language that is similar to JavaScript, but with features for blockchain development.

💡Foundry

Foundry is a development framework for Ethereum smart contracts that simplifies the process of building, testing, and deploying contracts. It provides a set of tools and a local development environment that allows developers to work on smart contracts more efficiently.

💡Curve Pool

Curve Pool refers to a liquidity pool on the Curve Finance platform, which is a decentralized exchange (DEX) that allows for automated market making and trading of stablecoins. Users can provide liquidity to these pools to earn rewards.

💡Liquidity Provider (LP) Token

Liquidity Provider (LP) Token is a type of token that represents an individual's share of a liquidity pool in a decentralized exchange. By providing liquidity, users earn LP tokens, which entitle them to a portion of the trading fees generated by the pool.

💡Virtual Price

Virtual Price is a term used in automated market making (AMM) platforms like Curve to represent the estimated price of the assets in the pool. It is a calculated value that reflects the current state of the pool and the relative value of the assets within it.

💡Add Liquidity

Adding liquidity to a decentralized exchange pool involves depositing assets into the pool, usually in exchange for LP tokens. This process helps to increase the overall liquidity of the pool, allowing for smoother trading and potentially earning rewards for the liquidity provider.

💡Remove Liquidity

Removing liquidity from a decentralized exchange pool is the process of withdrawing assets from the pool, usually in exchange for the LP tokens held by the liquidity provider. This action decreases the overall liquidity of the pool and allows the provider to claim their share of the trading fees and any price changes.

Highlights

Explaining the concept of re-entrancy hack where a contract calls a Target contract which then calls back into the original contract.

Describing the process of a re-entrant hack involving two calls to the Target contract and the execution sequence.

Introducing a read-only re-entrancy attack which is more complex and involves the hack contract calling a 'date contract' which then calls back.

Providing an example of a read-only re-entrancy attack on the Curve pool, executed as a simulation on the main network.

Installing and setting up Foundry for the purpose of writing smart contracts and simulating the attack.

Initializing a Foundry project and preparing the environment for writing code related to the re-entrancy attack.

Creating a new contract named 'hack' and defining its structure and purpose for the attack.

Setting up the addresses for the Curve pool and the liquidity provider (LP) token involved in the attack.

Writing the interface functions for the Curve contract and the ERC20 token standard to be used in the attack.

Describing the steps of the attack which include adding liquidity, logging the share value, and then removing liquidity to trigger the attack.

Explaining the timing of the attack where the 'remove liquidity' function sends Ether back before fully executing, allowing for the re-entrant call.

Writing the 'hack' contract's code to perform the attack by adding and removing liquidity from the Curve pool and exploiting the timing window.

Compiling the 'hack' contract and preparing to write a test to verify the effectiveness of the read-only re-entrancy attack.

Renaming the test file and contract to 'hack.test' and importing the necessary modules for the test environment.

Setting up the test function 'setUp' to initialize the 'hack' contract and prepare for the attack simulation.

Writing the 'testAll' function to execute the attack simulation and send a specified amount of Ether to trigger the attack.

Running the test on the main network using a fork URL from Alchemy API to simulate real network conditions.

Analyzing the logs to confirm that the 'get virtual price' is higher during the 'remove liquidity' execution, indicating a successful read-only re-entrancy.

Explaining the next step of exploiting another contract that depends on the 'get virtual price' value by calling it during the re-entrant attack.

Transcripts

play00:00

in a re-entrancy hack a contract will

play00:02

call a Target contract this Target

play00:04

contract will call back into the caller

play00:06

in this case the hack contract well the

play00:08

first call has now finished this hack

play00:10

contract will call back into the Target

play00:12

contract this is re-engine C hack a

play00:14

read-only re-entracy is a little bit

play00:16

more complicated first the hack contract

play00:18

will call into a contract we'll call

play00:21

this contract date contract day will

play00:23

call back into the caller in this case

play00:25

it will be the hack contract at this

play00:27

moment the call made in the first step

play00:29

to contract day has not yet finished

play00:31

while the call in the first step is not

play00:33

yet finished this hack contract will

play00:35

call into a Target contract the Target

play00:38

contract will read some state from

play00:39

contract day finish executing step 3

play00:42

after the function call to the Target

play00:44

contract finishes then the execution to

play00:46

step 2 finishes and thus leader

play00:49

execution to step 1 finishes let's take

play00:51

a look at an example for this example

play00:53

I'll be using Foundry so first let's

play00:55

install it I'll install Foundry by

play00:57

copying and pasting this command into my

play00:59

terminal all of the command and the

play01:01

codes that I'll be typing I'll put it up

play01:03

on GitHub

play01:05

the next step of installing Foundry is

play01:07

to type Foundry up so I'll type Foundry

play01:10

up

play01:12

next I'll initialize The Foundry project

play01:14

inside this directory by typing Forge

play01:17

init okay once that command executed

play01:19

successfully if I check the current

play01:22

directory you can see some files that

play01:23

Foundry put in and we're now ready to

play01:26

write some code for the read-only

play01:27

reentrc example for this example you'll

play01:30

simulate a read-only reentrancy attack

play01:32

on the curb sde pool and we'll be

play01:35

executing this on the main Network so we

play01:38

won't be actually hacking the contract

play01:39

we will just be running a simulation

play01:41

first I'll open source folder and then

play01:45

remove this boilerplate code

play01:49

and then I'll create a new contract

play01:52

called hack dot so first I'll paste the

play01:54

solidity version next I'll import

play01:57

console.tool so that you'll be able to

play01:58

console log some values inside a

play02:00

transaction next I'll set the address

play02:02

for the curb sde pool and the token that

play02:05

you get when you deposit into this pool

play02:06

I'll name it LP for liquidity provider

play02:09

we're going to be hacking the curb

play02:10

contract so I'll paste the interface for

play02:13

the curb

play02:14

for this example the functions that

play02:16

we're going to be calling is get virtual

play02:17

price add liquidity and remove liquidity

play02:20

when you call this function get virtual

play02:22

price it Returns the value of the shares

play02:24

the higher the value of the shares the

play02:26

more tokens that you'll get that is

play02:28

locked inside the pool when you call the

play02:29

function withdrawal we can add the

play02:31

tokens to this curve pool by calling the

play02:33

function add liquidity and to remove the

play02:35

tokens from this pool we'll be calling

play02:37

the function remove liquidity we're also

play02:39

going to need the irc20 interface so

play02:41

I'll paste it here okay so next let's

play02:43

write the hack contract so I'll type

play02:46

contract hack first let's set some

play02:50

contact addresses I curve this will be

play02:53

private constant and I'll name it pool

play02:56

and this is equal to I curve this is the

play03:00

interface that we defined above and the

play03:02

address of the pool that we'll be

play03:03

calling is St E4 I also set the irc20

play03:07

for the lp tokens so ierc

play03:11

25A constant LP token and this will be

play03:17

irc20 for the lp this is the token that

play03:20

we'll receive when we call the function

play03:22

at liquidity on the purple next I'll

play03:25

write the function called Palm this will

play03:29

be external and payable since we will be

play03:33

sending some leave this will be the main

play03:34

function that we will be calling to

play03:36

initiate the attack so what we're going

play03:39

to be doing is to First add liquidity to

play03:42

the curve pool next we'll log the value

play03:45

of the shares by calling the function

play03:46

get virtual price

play03:48

log get virtual price and then we'll

play03:52

remove

play03:53

liquidity by calling this function we'll

play03:56

be able to trigger the read-only

play03:58

reagency attack

play04:00

when we call the function remove

play04:01

liquidity on the curb as the E4 and then

play04:04

if I scroll down you can see here that

play04:07

it sends the if back before the function

play04:10

finishes executing so this means that

play04:13

when we call the function remove

play04:14

liquidity the code will execute and then

play04:17

before it finishes executing all of the

play04:20

code it will send some leave so this is

play04:22

where we can do the reagency back inside

play04:25

my code editor and back inside our

play04:27

contract when we call the function

play04:28

remove liquidity at some point it would

play04:31

send the if back to this contract so

play04:34

inside this contract I'll Define a

play04:35

receive external payable and this is

play04:39

where we will write our rest of our code

play04:41

to execute the read-only reentrancy in

play04:44

this example to show you the get virtual

play04:46

price will be higher while we're still

play04:49

executing remove liquidity inside here

play04:52

we will log get virtual price again okay

play04:57

let's write our code the first thing is

play04:59

to add liquidity now if I scroll up to

play05:02

call add liquidity on the curvepool

play05:04

we'll need to prepare a array up to

play05:06

specifying the amount of tokens to add

play05:08

and

play05:09

the minimum amount of LP tokens to make

play05:12

so scroll down first we'll initialize

play05:15

the inventory of two unit two

play05:18

memory or call it amounts and this will

play05:22

be equal to the first value represents

play05:24

the amount of beef that we're going to

play05:26

be sending so you'll be sending

play05:28

message.value the second amount

play05:30

represents the amount of stf that we're

play05:32

sending we will be sending zero and then

play05:34

we'll add liquidity by calling

play05:37

pull dot add liquidity

play05:40

passing in the amounts and the minimum

play05:43

amount of LPS that will be minting we'll

play05:46

say one and when we call this function

play05:48

that liquidity since this is the if sde4

play05:52

we'll have to also send the amount of

play05:54

beef that is specified over here so say

play05:58

value is message dot value when we call

play06:02

this function that liquidity it Returns

play06:04

the amount of LP tokens that were minted

play06:07

so I'll say uint LP equals to and that

play06:10

is ADD liquidity next we'll log the

play06:12

virtual price the value of one share of

play06:16

these LP tokens so I'll say

play06:19

console.log then I'll type

play06:22

before

play06:24

remove LP

play06:27

virtual price and then call the function

play06:30

pool dot get virtual price and then

play06:33

we'll remove liquidity let's scroll up

play06:36

to call remove liquidity we'll need to

play06:38

pass in the amount of LP tokens that

play06:40

we're going to be burning and the

play06:41

minimum amount of underlying token this

play06:44

will be if and sde that we expect to

play06:46

receive so scroll down we'll prepare a

play06:49

uint array of size 2 unit 2 memory Min

play06:55

amounts for this example I'll just say

play06:57

minimum amounts at 0 U and zero uint

play07:01

zero and then we'll call the function

play07:03

remove pool Dot remove liquidity passing

play07:07

in the amount of LP tokens that we're

play07:09

going to be burning we'll withdraw all

play07:11

of it so we'll pass in all of our LP

play07:13

tokens and pass in minimum amounts when

play07:16

we call this function remove liquidity

play07:17

at some point it will send us back the

play07:20

eve which will trigger the receive

play07:22

function so inside here we'll log the

play07:26

get virtual price so I'll copy this

play07:29

paste it here and then say during remove

play07:33

liquidity log the virtual price okay

play07:35

this completes the first step of our

play07:37

hack contract what we're trying to see

play07:40

here is that while we're calling remove

play07:42

liquidity we should see that get virtual

play07:45

price is higher and by confirming that

play07:48

get virtual price will be higher while

play07:50

this part of the function is executing

play07:52

we'll be able to write our exploit

play07:55

inside this receive function so let's

play07:57

first check the get virtual price is

play07:59

actually higher inside this part of the

play08:01

code so I'll open my terminal and then

play08:04

I'll try to compile the contract by

play08:06

typing Forge build now notice that the

play08:10

contract didn't compile because there

play08:12

was a contract in the test file that we

play08:14

deleted so I'll go fix that right now

play08:17

open the test and then remove the

play08:20

Imports

play08:23

and then remove all of the code inside

play08:25

the test and let's try compiling again

play08:29

okay our contract compiles let's now

play08:31

write the test a rename counter to

play08:37

hack.t.soul and also rename the test

play08:40

contract to hack test instead of

play08:43

importing a counter we'll import the

play08:45

hack contract and then inside our test

play08:48

contract I'll also import the console

play08:50

from Forge STD so copy this

play08:54

paste it here and then first we'll

play08:57

initialize the hack contract so I'll

play08:59

type hack public hack and then we'll

play09:04

write the function to set up the test

play09:06

function set up public then we'll

play09:10

initialize the hack contract pack is

play09:13

equal to new hack next we'll write a

play09:16

function to test our poem function

play09:18

function test all

play09:22

public and then we'll call the function

play09:24

hack dot poem when we call this function

play09:27

let's send hundred thousand if so I'll

play09:30

say value 100

play09:33

000 times 18. okay that's execute the

play09:36

test so when we call the function Palm

play09:39

we should see that get virtual price

play09:42

will be higher inside the receive

play09:45

function compared to what we get when we

play09:48

call the function get virtual price

play09:49

inside the pawn so I'll open my terminal

play09:53

clear the logs and then we'll be running

play09:55

a test on the main Network I'll copy the

play09:58

address for the fork URL that I got from

play10:00

Alchemy API I'll paste this command

play10:03

sending the fork URL to the Alchemy API

play10:06

and then we'll execute the test by

play10:08

calling Forge test Dash I'll put in Four

play10:12

B's BBB and this will print out of other

play10:16

logs when we run the test then we'll say

play10:19

fork URL is Fork URL from what we set

play10:25

above and then hit enter

play10:28

okay our test finished executing and you

play10:31

can see that there is a lot of logs this

play10:34

is because if I scroll up I put in Four

play10:37

B's and this means that it would print a

play10:40

lot of logs for this execution what I am

play10:42

interested is in the virtual price

play10:45

before removing liquidity and the

play10:47

virtual price during removing liquidity

play10:49

let's take a look before removing

play10:51

liquidity it is this amount that you see

play10:54

over here and during when we're removing

play10:56

liquidity you can see that the virtual

play10:58

price has gone up by a little bit ecf5

play11:01

over here and you see a 9 over here what

play11:03

this means is that if we target another

play11:05

contract that depends on Virtual price

play11:07

and then call that contract while we're

play11:10

removing liquidity we'll be able to

play11:12

exploit that contract that will be the

play11:14

next step okay I'm back in my hack

play11:16

contract and what we're going to do next

play11:18

is write an example contract to Target a

play11:21

contract to exploit inside the function

play11:23

received so first I'll write a Target

play11:26

contract that we'll be using for this

play11:29

example so I'll say contract

play11:31

Target and let's imagine that this

play11:33

Target contract you'll be able to State

play11:36

the lp tokens and you'll get some kind

play11:39

of rewards where the rewards is

play11:41

calculated based on the value returned

play11:43

by get virtual price so first I'll copy

play11:47

these to contract addresses and instead

play11:50

of LP token here I'll name it token I'll

play11:53

rename it to token so let's imagine that

play11:55

this contract has three functions a

play11:57

function to stake the tokens

play12:00

a function to unstake the lp tokens and

play12:04

some kind of function to get rewards

play12:06

based on the amount of tokens that we

play12:08

stick function get viewed okay let's

play12:12

fill in the details so stake it will

play12:15

take in the amount of LP tokens to State

play12:18

this will be external and when we call

play12:20

this function let's say that it

play12:22

transfers the token transfer from from

play12:25

message dot sender to this contract

play12:28

address this for the amount amount from

play12:31

the input

play12:32

and then let's say that it keeps track

play12:34

of the amount of tokens that is state so

play12:37

create a mapping

play12:39

from address to uint this will be public

play12:42

I'll name a balance up then when we

play12:46

stake it will update the balance of for

play12:48

message dot sender incremented by amount

play12:52

okay scrolling down when we on stake

play12:55

we'll be able to unstick the amount this

play12:57

will be external when we on state we'll

play13:00

first update the balance of message dot

play13:04

sender decremented by amount and then

play13:07

we'll transfer the token token dot

play13:10

transfer to message dot sender for the

play13:13

amount okay the last function we'll

play13:16

write is get rewards so this will be

play13:18

external

play13:20

returns let's say that it just Returns

play13:22

the amount of tokens amount of rewards

play13:24

tokens that we earn we'll set the amount

play13:27

of rewards token that we earn is we

play13:29

multiply the amount of state by the

play13:32

value of shares and the value of shares

play13:34

we get it by calling get virtual price

play13:36

on the curvepool so say unit

play13:40

reward is equal to balance of message

play13:43

dot sender times get virtual price pool

play13:46

dot get virtual price now both the lp

play13:50

tokens and get virtual price has 18

play13:52

decimals so what we'll have to do is

play13:55

divide by 10 to the 18. if we multiply

play13:58

balance all which has 18 decimals and

play14:01

get virtual price which has 18 decimals

play14:04

this multiplication now has 36 decimals

play14:08

so to get it back down to 18 decimals

play14:11

again we'll have to divide by 10 to the

play14:13

18. and then we'll have some code to

play14:16

transfer the reward go to transfer

play14:20

reward but for this example we'll just

play14:22

omit it

play14:24

escape code to transfer reward and for

play14:27

this example we'll just return the

play14:29

amount of reward that was calculated

play14:31

okay let's try compiling this contract

play14:34

clear the logs and then type Forge build

play14:39

look at the contract compiled

play14:40

successfully so let's move on to write

play14:42

some exploit inside the hack contract so

play14:45

scrolling down to the hack contract

play14:46

first I'll store the Target contract

play14:50

inside the hack contract so I'll say

play14:51

Target

play14:52

private immutable Target and then Define

play14:57

a Constructor Constructor we'll take in

play15:00

the address of the target

play15:02

and then we'll set the target target

play15:04

equal to

play15:07

Target address of Target

play15:09

now what we're going to do is before we

play15:13

call the function poem we'll stake some

play15:15

LP tokens into the Target contract and

play15:19

then afterwards we call the function

play15:21

poem this will eventually call remove

play15:24

liquidity which we'll call the receive

play15:26

function inside here we know that get

play15:28

virtual price is overpriced so inside

play15:32

here we'll call the function get reward

play15:35

On Target and we should get more rewards

play15:38

than what we should have if we didn't do

play15:41

the exploit okay so let's do that so

play15:44

first I'll create a function called

play15:48

set up this will be external

play15:51

payable and inside here we'll deposit

play15:55

we'll stake some tokens into the Target

play15:57

contract so first we'll need to add

play16:00

liquidity copy this paste it here and

play16:03

then we will transfer this LP token over

play16:06

to the Target contract so LP token Dot

play16:10

approve address of the target

play16:14

for the amount LP and then call Target

play16:18

Dot take LP next we'll execute the pawn

play16:24

function and this will execute remove

play16:27

liquidity which will execute receipt and

play16:30

inside here let's get the reward by

play16:32

calling uint reward is equal to Target

play16:36

dot get keyboard and then for this

play16:40

example we'll log the amount of rewards

play16:42

that we earned if we had called get

play16:45

reward inside the receive function so

play16:48

say console.log

play16:50

reward

play16:52

reward and then we'll also compare this

play16:56

amount of rewards that we would have got

play16:59

compared to how much reward we will get

play17:02

if we call it after the read-only

play17:04

reentrancy is done so if we did not

play17:07

execute our read-only reentrency how

play17:09

much reward will we get

play17:13

I'll copy these two code

play17:16

and then paste it here

play17:18

okay let's update our test so back

play17:21

inside the hack test contract I know

play17:23

that we'll need to deploy the Target

play17:25

contract so Target public

play17:28

Target and then we'll deploy the Target

play17:31

contract first Target

play17:33

is equal to new Target

play17:36

and now the hack contract takes in the

play17:39

address of the target so inside the

play17:40

Constructor I'll pass in the address of

play17:42

the

play17:43

Target and then before we call the

play17:45

function Palm you'll need to call the

play17:48

function setup to stake some of our LP

play17:51

tokens into the Target contract so here

play17:55

hack not

play17:57

setup and when we call this function

play17:59

setup we'll get some LP tokens from the

play18:02

pool from the curb SD E4 and then stake

play18:05

it so let's send some if so I'll say

play18:08

value we'll send 10 if 10 times 10 to

play18:12

the 18. okay let's try compounding

play18:14

contract I'll open the terminal clear

play18:17

the logs and then type Forge build

play18:20

and a contract compiles so let's now run

play18:23

the test again

play18:24

and our test was successful let's check

play18:27

the logs scroll up

play18:33

before we remove liquidity get virtual

play18:36

price return some amount during the lp

play18:39

is being removed so this will be the

play18:42

code that was executed inside the

play18:44

receive function get virtual price was

play18:47

slightly higher and when we call the

play18:50

function get reward we would have gotten

play18:52

this much amount whereas after remove

play18:54

liquidity is done executing and then we

play18:57

call get reward we get a slightly thus

play18:59

amount this means that if we were to

play19:01

call get reward while the liquidity was

play19:04

being removed then we would have gotten

play19:06

more rewards than calling get reward

play19:08

after recalled remove liquidity that was

play19:11

an example of read-only reentrancy where

play19:14

we wrote Our hack contract and then we

play19:16

called the curb SD info we called it by

play19:19

calling the function remove liquidity

play19:21

and then while the remove liquidity is

play19:23

executing it transferred some if and

play19:26

then inside here it executed the code

play19:28

inside the receive which allowed us to

play19:31

call the Target contract get keyboard

play19:33

get reward calculated the amount of

play19:36

rewards by calling get virtual price

play19:38

inside the curve pool at this point the

play19:41

virtual price is slightly higher than

play19:44

what it should be so by the time all of

play19:47

this finished executing we were able to

play19:49

get more rewards than what we would have

play19:51

if we did not execute the read-only

play19:54

re-engency

Rate This
★
★
★
★
★

5.0 / 5 (0 votes)

Étiquettes Connexes
SmartContractsReentrancyHacksCurvePoolSolidityFoundrySecurityVulnerabilitiesBlockchainSecurityHackingTutorialsCryptocurrencyDeFi
Besoin d'un résumé en anglais ?