<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maxwell</title>
    <description>The latest articles on DEV Community by Maxwell (@maxi_1769).</description>
    <link>https://dev.to/maxi_1769</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4101066%2Fef367276-f76c-4797-a434-5c25d5e23110.jpg</url>
      <title>DEV Community: Maxwell</title>
      <link>https://dev.to/maxi_1769</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxi_1769"/>
    <language>en</language>
    <item>
      <title>Building StakeVault: A Full-Stack DeFi Staking Protocol with Solidity, Foundry, React and Ethers.js</title>
      <dc:creator>Maxwell</dc:creator>
      <pubDate>Sun, 30 Aug 2026 07:03:14 +0000</pubDate>
      <link>https://dev.to/maxi_1769/building-stakevault-a-full-stack-defi-staking-protocol-with-solidity-foundry-react-and-ethersjs-33ph</link>
      <guid>https://dev.to/maxi_1769/building-stakevault-a-full-stack-defi-staking-protocol-with-solidity-foundry-react-and-ethersjs-33ph</guid>
      <description>&lt;h1&gt;
  
  
  Building StakeVault: A Full-Stack DeFi Staking Protocol with Solidity, Foundry, React and Ethers.js
&lt;/h1&gt;

&lt;p&gt;StakeVault is a decentralized staking protocol where users deposit STAKE tokens into a smart contract and earn REWARD tokens over time.&lt;/p&gt;

&lt;p&gt;The project was built as a full-stack Web3 application combining Solidity smart contracts with a React frontend. The protocol is deployed on Ethereum Sepolia and can be interacted with through a connected Web3 wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;StakeVault consists of three primary smart contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;StakeToken&lt;/code&gt; — the ERC-20 token users stake.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RewardToken&lt;/code&gt; — the ERC-20 token distributed as rewards.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StakingVault&lt;/code&gt; — the core contract responsible for staking, reward accounting, withdrawals, reward claims and reward funding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend was built using React and Vite and communicates with the deployed contracts using Ethers.js and Wagmi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Project
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://defi-staking-dhzkby4cm-wire4.vercel.app/" rel="noopener noreferrer"&gt;https://defi-staking-dhzkby4cm-wire4.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/max-wire/defi-staking" rel="noopener noreferrer"&gt;https://github.com/max-wire/defi-staking&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How Staking Works
&lt;/h2&gt;

&lt;p&gt;The basic flow is:&lt;/p&gt;

&lt;p&gt;User&lt;br&gt;
↓&lt;br&gt;
Approve STAKE&lt;br&gt;
↓&lt;br&gt;
&lt;code&gt;StakeToken.approve()&lt;/code&gt;&lt;br&gt;
↓&lt;br&gt;
&lt;code&gt;StakingVault.stake()&lt;/code&gt;&lt;br&gt;
↓&lt;br&gt;
User staking position increases&lt;br&gt;
↓&lt;br&gt;
Global total stake increases&lt;br&gt;
↓&lt;br&gt;
Reward accounting updates&lt;br&gt;
↓&lt;br&gt;
Time passes&lt;br&gt;
↓&lt;br&gt;
Rewards accrue&lt;br&gt;
↓&lt;br&gt;
&lt;code&gt;claimRewards()&lt;/code&gt; or &lt;code&gt;exit()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The frontend provides a simple interface for performing these operations without requiring users to interact with the smart contracts manually.&lt;/p&gt;
&lt;h2&gt;
  
  
  Global Staking vs User Staking
&lt;/h2&gt;

&lt;p&gt;One important design aspect of StakeVault is the distinction between the global protocol state and an individual user's position.&lt;/p&gt;

&lt;p&gt;For example, if User A stakes 410 STAKE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User A's staked amount becomes 410 STAKE.&lt;/li&gt;
&lt;li&gt;The global &lt;code&gt;totalStaked&lt;/code&gt; value also becomes 410 STAKE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If User B subsequently stakes 10 STAKE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User A still has 410 STAKE.&lt;/li&gt;
&lt;li&gt;User B has 10 STAKE.&lt;/li&gt;
&lt;li&gt;The global protocol total becomes 420 STAKE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, &lt;code&gt;Total Staked&lt;/code&gt; on the dashboard represents the amount currently deposited across the entire staking pool, not the connected wallet's individual position.&lt;/p&gt;
&lt;h2&gt;
  
  
  Finite Reward Pool
&lt;/h2&gt;

&lt;p&gt;A major design decision in StakeVault is the use of a finite reward pool.&lt;/p&gt;

&lt;p&gt;The vault maintains a &lt;code&gt;rewardRemaining&lt;/code&gt; value representing the amount of REWARD tokens available for distribution.&lt;/p&gt;

&lt;p&gt;Rewards are emitted over time according to the configured reward rate, but the protocol cannot continue creating reward liabilities after the funded pool has been exhausted.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;Reward Pool&lt;br&gt;
↓&lt;br&gt;
&lt;code&gt;rewardRemaining&lt;/code&gt;&lt;br&gt;
↓&lt;br&gt;
Rewards emitted over time&lt;br&gt;
↓&lt;br&gt;
Users accrue rewards&lt;br&gt;
↓&lt;br&gt;
Pool reaches zero&lt;br&gt;
↓&lt;br&gt;
Reward emissions stop&lt;/p&gt;

&lt;p&gt;Additional REWARD tokens can be funded into the vault to continue distribution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reward Accounting
&lt;/h2&gt;

&lt;p&gt;Rewards are calculated using cumulative &lt;code&gt;rewardPerToken&lt;/code&gt; accounting.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rewardPerToken =
    rewardPerTokenStored
    + (newRewards × PRECISION / totalStaked)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A user's accrued rewards depend on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Their staking balance&lt;/li&gt;
&lt;li&gt;The total amount staked&lt;/li&gt;
&lt;li&gt;Time elapsed&lt;/li&gt;
&lt;li&gt;The configured reward rate&lt;/li&gt;
&lt;li&gt;The remaining reward pool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows multiple users to participate in the same staking pool while maintaining separate individual positions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;The React frontend provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wallet connection&lt;/li&gt;
&lt;li&gt;STAKE balance&lt;/li&gt;
&lt;li&gt;REWARD balance&lt;/li&gt;
&lt;li&gt;Individual staked amount&lt;/li&gt;
&lt;li&gt;Global total staked&lt;/li&gt;
&lt;li&gt;Reward rate&lt;/li&gt;
&lt;li&gt;Remaining rewards&lt;/li&gt;
&lt;li&gt;Token approval&lt;/li&gt;
&lt;li&gt;Staking&lt;/li&gt;
&lt;li&gt;Withdrawals&lt;/li&gt;
&lt;li&gt;Reward claiming&lt;/li&gt;
&lt;li&gt;Exit functionality&lt;/li&gt;
&lt;li&gt;Automatic blockchain data refresh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface also performs a balance check before requesting token approval. This prevents users from signing an approval transaction when they do not have enough STAKE to perform the requested staking operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;The smart contract system was tested using Foundry.&lt;/p&gt;

&lt;p&gt;The test suite covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ERC-20 token behavior&lt;/li&gt;
&lt;li&gt;Staking&lt;/li&gt;
&lt;li&gt;Multiple staking operations&lt;/li&gt;
&lt;li&gt;Withdrawals&lt;/li&gt;
&lt;li&gt;Reward accrual&lt;/li&gt;
&lt;li&gt;Proportional reward distribution&lt;/li&gt;
&lt;li&gt;Multiple-user reward calculations&lt;/li&gt;
&lt;li&gt;Reward claiming&lt;/li&gt;
&lt;li&gt;Exit functionality&lt;/li&gt;
&lt;li&gt;Reward funding&lt;/li&gt;
&lt;li&gt;Reward rate updates&lt;/li&gt;
&lt;li&gt;Pause and unpause functionality&lt;/li&gt;
&lt;li&gt;Reward pool exhaustion&lt;/li&gt;
&lt;li&gt;Accounting invariants&lt;/li&gt;
&lt;li&gt;Edge cases and failure conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project currently contains 80 passing Foundry tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For detailed traces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-vvv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ethereum Sepolia Deployment
&lt;/h2&gt;

&lt;p&gt;The production testnet deployment runs on Ethereum Sepolia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network:&lt;/strong&gt; Ethereum Sepolia&lt;br&gt;
&lt;strong&gt;Chain ID:&lt;/strong&gt; &lt;code&gt;11155111&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Contracts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StakeToken
0x6De64f2A0D3C1c93cECB67eF06D4a22ff6e00999

RewardToken
0x1D1A21d7468040b306d06E3f1c6c30eeD249F380

StakingVault
0x9A8a5DdEC15F4B8822BF10E849B5C465D6cf2C1e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Hash
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4ba73c3497f46ea64b0dd4e49ad8d02653085e82
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This identifies the Git commit associated with the documented project state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Smart Contracts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Solidity&lt;/li&gt;
&lt;li&gt;Foundry&lt;/li&gt;
&lt;li&gt;OpenZeppelin&lt;/li&gt;
&lt;li&gt;Anvil&lt;/li&gt;
&lt;li&gt;Ethereum Sepolia&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Ethers.js&lt;/li&gt;
&lt;li&gt;Wagmi&lt;/li&gt;
&lt;li&gt;WalletConnect&lt;/li&gt;
&lt;li&gt;MetaMask&lt;/li&gt;
&lt;li&gt;Coinbase Wallet&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try the Application
&lt;/h2&gt;

&lt;p&gt;The deployed application is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://defi-staking-dhzkby4cm-wire4.vercel.app/" rel="noopener noreferrer"&gt;https://defi-staking-dhzkby4cm-wire4.vercel.app/&lt;/a&gt;&lt;br&gt;
The project is open source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/max-wire/defi-staking" rel="noopener noreferrer"&gt;https://github.com/max-wire/defi-staking&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;This project was developed as part of the EtherAuthority Web3 training/internship program.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/etherauthority"&gt;@etherauthority&lt;/a&gt;&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/securechainai"&gt;@securechainai&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Web3 #Blockchain #Ethereum #SmartContracts #DeFi #Solidity #Web3Development #BlockchainDevelopment #Staking #DApp #ERC20 #SmartContractSecurity
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftl9awqbnyiu7xxhfnwuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftl9awqbnyiu7xxhfnwuw.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;                        &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyukna8msl21usf7iyn0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyukna8msl21usf7iyn0z.png" alt=" " width="799" height="388"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd035t8ax9fdwf9rugtnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd035t8ax9fdwf9rugtnv.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjlpke4qt2q3eon9mdfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjlpke4qt2q3eon9mdfa.png" alt=" " width="562" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6hhgwbq49vypxml1f3z5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6hhgwbq49vypxml1f3z5.png" alt=" " width="562" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mpo70bv9sfch5ezpvwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mpo70bv9sfch5ezpvwp.png" alt=" " width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa1f2nhfjazke0o2i9zla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa1f2nhfjazke0o2i9zla.png" alt=" " width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>defi</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
