Skip to content

shakams434/CH1

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🚩 Challenge #1: πŸ” Decentralized Staking App

readme-1

πŸ“š This tutorial is meant for developers that already understand the πŸ–οΈ basics: Starklings or Node Guardians

🦸 A superpower of Smart contracts is allowing you, the builder, to create a simple set of rules that an adversarial group of players can use to work together. In this challenge, you create a decentralized application where users can coordinate a group funding effort. If the users cooperate, the money is collected in a second smart contract. If they defect, the worst that can happen is everyone gets their money back. The users only have to trust the code.

🏦 Build a Staker.cairo contract that collects ETH from numerous addresses using a function stake() function and keeps track of balances. After some deadline if it has at least some threshold of ETH, it sends it to an ExampleExternalContract and triggers the complete() action sending the full balance. If not enough ETH is collected, allows users to withdraw().

πŸŽ› Building the frontend to display the information and UI is just as important as writing the contract. The goal is to deploy the contract and the app to allow anyone to stake using your app. Use a Stake {sender: ContractAddress, amount: u256} Starknet event to list all stakes.

🌟 The final deliverable is deploying a Dapp that lets users send ether to a contract and stake if the conditions are met, then yarn vercel your app to a public webserver.

πŸ’¬ Submit this challenge, meet other builders working on this challenge or get help in the Builders telegram chat!


Checkpoint 0: πŸ“¦ Environment πŸ“š

Before you begin, you need to install the following tools:

Compatible versions

  • Starknet-devnet - v0.2.3
  • Scarb - v2.9.2
  • Snforge - v0.35.1
  • Cairo - v2.9.2
  • Rpc - v0.7.1

Make sure you have the compatible versions otherwise refer to Scaffold-Stark Requirements

Docker Option for Environment Setup

For an alternative to local installations, you can use Docker to set up the environment.

Then download the challenge to your computer and install dependencies by running:

git clone https://github.com/Scaffold-Stark/speedrunstark.git challenge-1-decentralized-staking
cd challenge-1-decentralized-staking
git checkout challenge-1-decentralized-staking
yarn install

in the same terminal, start your local network (a blockchain emulator in your computer):

yarn chain

in a second terminal window, πŸ›° deploy your contract (locally):

cd challenge-1-decentralized-staking
yarn deploy

in a third terminal window, start your πŸ“± frontend:

cd challenge-1-decentralized-staking
yarn start

πŸ“± Open http://localhost:3000 to see the app.

πŸ‘©β€πŸ’» Rerun yarn deploy whenever you want to deploy new contracts to the frontend. If you haven't made any contract changes, you can run yarn deploy:reset for a completely fresh deploy.

πŸ” Now you are ready to edit your smart contract Staker.cairo in packages/sfoundry/contracts.


βš—οΈ At this point you will need to know basic Cairo syntax. If not, you can pick it up quickly by tinkering with concepts from πŸ“‘ The Cairo Book using πŸ—οΈ Scaffold-Stark. (In particular: Contract's State, storage variables, interface, mappings, events, traits, constructor, and public/private functions.)


Checkpoint 1: πŸ₯© Staking πŸ’΅

You'll need to track individual balances using a Map:

#[storage]
struct Storage {
 eth_token_dispatcher: IERC20CamelDispatcher,
 balances: Map<ContractAddress, u256>,
 ...
}

And also track a constant threshold at 1 ether.

const THRESHOLD: u256 = 1000000000000000000;

Checkpoint 1.1: Handling ETH Transactions in Starknet

In Starknet, ETH is managed as a token, which means you cannot directly send value through a transaction. Meaning you must approve ETH spending and then transfer it using a contract. This involves utilizing the predeployed ETH contract address in Starknet.

In this challenge, we’ll demonstrate how to handle ETH transactions by passing the ETH contract address as an argument to the contract constructor.

First, you have to define your constructor function in the Staker contract:

 #[constructor]
    pub fn constructor(
        ref self: ContractState,
        eth_contract: ContractAddress,
  ...
    ) 

Then, pass the eth_contract address as an argument to the deployContract function in the deploy.ts file:

  await deployContract({
    contract: "Staker",
    constructorArgs: {
      eth_contract:
        "0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7",
      ...
    },
  });

Next, import the IERC20CamelDispatcher struct from the OpenZeppelin library:

use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};

In the constructor function, instantiate the IERC20CamelDispatcher struct with the address of the ETH contract address:

self.eth_token_dispatcher.write(IERC20CamelDispatcher { contract_address: eth_contract });

With the dispatcher set up, you can now utilize functions defined in the interface, such as transfer, transferFrom, and balanceOf, to manage ETH transactions effectively.


πŸ‘©β€πŸ’» Write your stake() function and test it with the Debug Contracts tab in the frontend.

debugContracts

πŸ₯… Goals

  • Do you see the balance of the Staker contract go up when you stake()?

  • Is your balance correctly tracked?

  • Do you see the events in the Stake Events tab?

    allStakings


Checkpoint 2: πŸ”¬ State Machine / Timing ⏱

State Machine

βš™οΈ Think of your smart contract like a state machine. First, there is a stake period. Then, if you have gathered the threshold worth of ETH, there is a success state. Or, we go into a withdraw state to let users withdraw their funds.

Set a deadline of get_block_timestamp() + 60 in the constructor to allow 60 seconds for users to stake.

self.deadline.write(get_block_timestamp() + 60);

πŸ‘¨β€πŸ« Smart contracts can't execute automatically, you always need to have a transaction execute to change state. Because of this, you will need to have an execute() function that anyone can call, just once, after the deadline has expired.

πŸ‘©β€πŸ’» Write your execute() function and test it with the Debug Contracts tab

Check the ExampleExternalContract.cairo for the bool you can use to test if it has been completed or not. But do not edit the ExampleExternalContract.cairo as it can slow the auto grading.

If the staked amount of the contract:

let staked_amount = self.eth_token_dispatcher.read().balanceOf(get_contract_address())

Is over the threshold by the deadline, you will want to call: self.complete_transfer(staked_amount). This will send the funds to the ExampleExternalContract and call complete().

If the balance is less than the threshold, you want to set a open_for_withdraw bool to true which will allow users to withdraw() their funds.

Timing

You'll have 60 seconds after deploying until the deadline is reached, you can adjust this in the contract.

πŸ‘©β€πŸ’» Implement the time_left() function that returns how much time is left.

⚠️ Be careful! If get_block_timestamp() >= deadline you want to return 0;

⏳ "Time Left" will only update if a transaction occurs. You can see the time update by getting funds from the faucet button in navbar just to trigger a new block.

stakerUI

πŸ‘©β€πŸ’» You can call yarn deploy:reset any time you want a fresh contract, it will get re-deployed even if there are no changes on it.
You may need it when you want to reload the "Time Left" of your tests.

Your Staker UI tab should be almost done and working at this point.


πŸ₯… Goals

  • Can you see time_left() counting down in the Staker UI tab when you trigger a transaction with the faucet button?
  • If enough ETH is staked by the deadline, does your execute() function correctly call complete() and stake the ETH?
  • If the threshold isn't met by the deadline, are you able to withdraw() your funds?

Checkpoint 3: UX πŸ™Ž

πŸ₯… Goals

  • If you send ETH directly to the contract address does it update your balance and the balance of the contract?

βš”οΈ Side Quests

  • Can execute() get called more than once, and is that okay?
  • Can you stake and withdraw freely after the deadline, and is that okay?
  • What are other implications of anyone being able to withdraw for someone?

🐸 It's a trap

  • Make sure funds can't get trapped in the contract! Try sending funds after you have executed! What happens?
  • Implement the private function called not_completed. It will check that ExampleExternalContract is not completed yet. Use it to protect your execute and withdraw functions.

⚠️ Test it

  • Now is a good time to run yarn test to run the automated testing function. It will test that you hit the core checkpoints. You are looking for all green checkmarks and passing tests!

Checkpoint 4: πŸ’Ύ Deploy your contract! πŸ›°

πŸ“‘ Find the packages/nextjs/scaffold.config.ts file and change the targetNetworks to [chains.sepolia].

network

πŸ” Prepare your environment variables.

Find the packages/snfoundry/.env file and fill the env variables related to Sepolia testnet with your own wallet account address and private key.

⛽️ You will need to get some ETH or STRK Sepolia tokens to deploy your contract to Sepolia testnet.

πŸ“ If you plan on submitting this challenge, be sure to set your deadline to at least block.timestamp + 72 hours

πŸš€ Run yarn deploy --network [network] to deploy your smart contract to a public network (mainnet or sepolia).

you input yarn deploy --network sepolia.

allStakings-blockFrom

πŸ’¬ Hint: For faster loading of your "Stake Events" page, consider updating the fromBlock passed to useScaffoldEventHistory in packages/nextjs/app/stakings/page.tsx to blocknumber - 10 at which your contract was deployed. Example: fromBlock: 3750241n (where n represents its a BigInt). To find this blocknumber, search your contract's address on Starkscan and find the Contract Creation transaction line.


Checkpoint 5: 🚒 Ship your frontend! 🚁

🦊 Since we have deployed to a public testnet, you will now need to connect using a wallet you own(Argent X or Braavos).

πŸ’» View your frontend at http://localhost:3000/stakerUI and verify you see the correct network.

πŸ“‘ When you are ready to ship the frontend app...

πŸ“¦ Run yarn vercel to package up your frontend and deploy.

Follow the steps to deploy to Vercel. Once you log in (email, github, etc), the default options should work. It'll give you a public URL.

If you want to redeploy to the same production URL you can run yarn vercel --prod. If you omit the --prod flag it will deploy it to a preview/test URL.

Configuration of Third-Party Services for Production-Grade Apps

By default, πŸ— Scaffold-Stark provides predefined Open API endpoint for some services such as Blast. This allows you to begin developing and testing your applications more easily, avoiding the need to register for these services. This is great to complete your SpeedRunStark.

For production-grade applications, it's recommended to obtain your own API keys (to prevent rate limiting issues). You can configure these at:

πŸ”· RPC_URL_SEPOLIA variable in packages/snfoundry/.env and packages/nextjs/.env.local. You can create API keys from the Alchemy dashboard.

πŸ’¬ Hint: It's recommended to store env's for nextjs in Vercel/system env config for live apps and use .env.local for local testing.


πŸƒ Head to your next challenge here.

πŸ’¬ Problems, questions, comments on the stack? Post them to the πŸ— scaffold-stark developers chat

About

desafio1Starknet

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 16

Languages