From 42f36ea6c8838b1c34bb730973bb5c9c2c9eca6c Mon Sep 17 00:00:00 2001 From: kaksv Date: Sun, 4 May 2025 09:42:47 +0300 Subject: [PATCH 1/3] Kakooza Vianey | Register for OpenGuild x Encode Club Challenges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ee62858..fd9f924 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ git clone https://github.com/openguild-labs/open-encode-challenges.git Go to **Participant Registration** section and register to be the workshop participants. Add the below to the list, replace any placeholder with your personal information. ``` -| 🦄 | Name | Github username | Your current occupation | +| 🦄 | Kakooza Vianey | kaksv | Web3 Builder | ``` - Step 5: `Commit` your code and push to the forked Github repository From e96c3c031a13e0649aa4bcc18f762e0561272d67 Mon Sep 17 00:00:00 2001 From: kaksv Date: Tue, 6 May 2025 21:24:59 +0300 Subject: [PATCH 2/3] solved challenges --- challenge-1-vesting/README.md | 1 + .../contracts/TokenVesting.sol | 180 +- .../contracts/TokenVesting.txt | 168 + challenge-2-yield-farm/contracts/yeild.sol | 189 +- challenge-3-frontend/app/page.tsx | 109 +- challenge-3-frontend/app/providers.tsx | 19 +- challenge-3-frontend/app/vesting/page.tsx | 15 + .../app/yield-farm/loader.tsx | 17 + challenge-3-frontend/app/yield-farm/page.tsx | 14 + .../components/mint-mock-token.tsx | 102 + challenge-3-frontend/components/navbar.tsx | 65 +- challenge-3-frontend/components/stake.tsx | 439 ++ challenge-3-frontend/components/vesting.tsx | 243 + challenge-3-frontend/components/withdraw.tsx | 434 ++ .../components/yield-farm.tsx | 24 + challenge-3-frontend/lib/abi.ts | 5820 ++++++++++------- challenge-3-frontend/lib/config.ts | 7 + 17 files changed, 5087 insertions(+), 2759 deletions(-) create mode 100644 challenge-1-vesting/contracts/TokenVesting.txt create mode 100644 challenge-3-frontend/app/vesting/page.tsx create mode 100644 challenge-3-frontend/app/yield-farm/loader.tsx create mode 100644 challenge-3-frontend/app/yield-farm/page.tsx create mode 100644 challenge-3-frontend/components/mint-mock-token.tsx create mode 100644 challenge-3-frontend/components/stake.tsx create mode 100644 challenge-3-frontend/components/vesting.tsx create mode 100644 challenge-3-frontend/components/withdraw.tsx create mode 100644 challenge-3-frontend/components/yield-farm.tsx create mode 100644 challenge-3-frontend/lib/config.ts diff --git a/challenge-1-vesting/README.md b/challenge-1-vesting/README.md index 9cc7a2c..e8554d5 100644 --- a/challenge-1-vesting/README.md +++ b/challenge-1-vesting/README.md @@ -11,6 +11,7 @@ Add your information to the below list to officially participate in the workshop | Emoji | Name | Github Username | Occupations | | ----- | ---- | ------------------------------------- | ----------- | | 🎅 | Ippo | [NTP-996](https://github.com/NTP-996) | DevRel | +| 🎅 | Kakooza Vianey | [kaksv](https://github.com/kaksv/) | Web3 Developer | ## 💻 Local development environment setup diff --git a/challenge-1-vesting/contracts/TokenVesting.sol b/challenge-1-vesting/contracts/TokenVesting.sol index 43d4c3a..7218358 100644 --- a/challenge-1-vesting/contracts/TokenVesting.sol +++ b/challenge-1-vesting/contracts/TokenVesting.sol @@ -1,25 +1,3 @@ -// Challenge: Token Vesting Contract -/* -Create a token vesting contract with the following requirements: - -1. The contract should allow an admin to create vesting schedules for different beneficiaries -2. Each vesting schedule should have: - - Total amount of tokens to be vested - - Cliff period (time before any tokens can be claimed) - - Vesting duration (total time for all tokens to vest) - - Start time -3. After the cliff period, tokens should vest linearly over time -4. Beneficiaries should be able to claim their vested tokens at any time -5. Admin should be able to revoke unvested tokens from a beneficiary - -Bonus challenges: -- Add support for multiple token types -- Implement a whitelist for beneficiaries -- Add emergency pause functionality - -Here's your starter code: -*/ - // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; @@ -28,50 +6,35 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; -contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { +contract TokenVesting is Ownable, Pausable, ReentrancyGuard { struct VestingSchedule { - // TODO: Define the vesting schedule struct + uint256 totalAmount; + uint256 startTime; + uint256 cliffDuration; + uint256 vestingDuration; + uint256 amountClaimed; + bool revoked; } - // Token being vested - // TODO: Add state variables - - - // Mapping from beneficiary to vesting schedule - // TODO: Add state variables + IERC20 public token; + mapping(address => VestingSchedule) public vestingSchedules; + mapping(address => bool) public whitelist; - // Whitelist of beneficiaries - // TODO: Add state variables - - // Events event VestingScheduleCreated(address indexed beneficiary, uint256 amount); event TokensClaimed(address indexed beneficiary, uint256 amount); event VestingRevoked(address indexed beneficiary); event BeneficiaryWhitelisted(address indexed beneficiary); event BeneficiaryRemovedFromWhitelist(address indexed beneficiary); - constructor(address tokenAddress) { - // TODO: Initialize the contract - + constructor(address tokenAddress) Ownable(msg.sender) { + token = IERC20(tokenAddress); } - // Modifier to check if beneficiary is whitelisted modifier onlyWhitelisted(address beneficiary) { require(whitelist[beneficiary], "Beneficiary not whitelisted"); _; } - function addToWhitelist(address beneficiary) external onlyOwner { - require(beneficiary != address(0), "Invalid address"); - whitelist[beneficiary] = true; - emit BeneficiaryWhitelisted(beneficiary); - } - - function removeFromWhitelist(address beneficiary) external onlyOwner { - whitelist[beneficiary] = false; - emit BeneficiaryRemovedFromWhitelist(beneficiary); - } - function createVestingSchedule( address beneficiary, uint256 amount, @@ -79,22 +42,84 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { uint256 vestingDuration, uint256 startTime ) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused { - // TODO: Implement vesting schedule creation + require(amount > 0, "Amount must be positive"); + require(cliffDuration <= vestingDuration, "Cliff exceeds duration"); + require(vestingDuration > 0, "Duration must be positive"); + require(startTime >= block.timestamp, "Start time in past"); + require(vestingSchedules[beneficiary].totalAmount == 0, "Schedule exists"); + + token.transferFrom(msg.sender, address(this), amount); + + vestingSchedules[beneficiary] = VestingSchedule({ + totalAmount: amount, + startTime: startTime, + cliffDuration: cliffDuration, + vestingDuration: vestingDuration, + amountClaimed: 0, + revoked: false + }); + + emit VestingScheduleCreated(beneficiary, amount); } - function calculateVestedAmount( - address beneficiary - ) public view returns (uint256) { - // TODO: Implement vested amount calculation + function calculateVestedAmount(address beneficiary) public view returns (uint256) { + VestingSchedule memory schedule = vestingSchedules[beneficiary]; + if (schedule.totalAmount == 0) return 0; + + uint256 currentTime = block.timestamp; + if (currentTime < schedule.startTime) return 0; + + uint256 elapsed = currentTime - schedule.startTime; + if (elapsed < schedule.cliffDuration) return 0; + + if (elapsed >= schedule.vestingDuration || schedule.revoked) { + return schedule.totalAmount - schedule.amountClaimed; + } + + uint256 vested = (schedule.totalAmount * elapsed) / schedule.vestingDuration; + return vested - schedule.amountClaimed; } function claimVestedTokens() external nonReentrant whenNotPaused { - // TODO: Implement token claiming + VestingSchedule storage schedule = vestingSchedules[msg.sender]; + require(schedule.totalAmount > 0, "No vesting schedule"); + + uint256 vestedAmount = calculateVestedAmount(msg.sender); + require(vestedAmount > 0, "No tokens to claim"); + + schedule.amountClaimed += vestedAmount; + token.transfer(msg.sender, vestedAmount); + + emit TokensClaimed(msg.sender, vestedAmount); } function revokeVesting(address beneficiary) external onlyOwner { - // TODO: Implement vesting revocation + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + require(schedule.totalAmount > 0, "No vesting schedule"); + require(!schedule.revoked, "Already revoked"); + + uint256 vestedAmount = calculateVestedAmount(beneficiary); + uint256 unvested = schedule.totalAmount - vestedAmount; + + schedule.totalAmount = vestedAmount; + schedule.revoked = true; + + if (unvested > 0) { + token.transfer(owner(), unvested); + } + + emit VestingRevoked(beneficiary); + } + function addToWhitelist(address beneficiary) external onlyOwner { + require(beneficiary != address(0), "Invalid address"); + whitelist[beneficiary] = true; + emit BeneficiaryWhitelisted(beneficiary); + } + + function removeFromWhitelist(address beneficiary) external onlyOwner { + whitelist[beneficiary] = false; + emit BeneficiaryRemovedFromWhitelist(beneficiary); } function pause() external onlyOwner { @@ -104,45 +129,4 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { function unpause() external onlyOwner { _unpause(); } -} - -/* -Solution template (key points to implement): - -1. VestingSchedule struct should contain: - - Total amount - - Start time - - Cliff duration - - Vesting duration - - Amount claimed - - Revoked status - -2. State variables needed: - - Mapping of beneficiary address to VestingSchedule - - ERC20 token reference - - Owner/admin address - -3. createVestingSchedule should: - - Validate input parameters - - Create new vesting schedule - - Transfer tokens to contract - - Emit event - -4. calculateVestedAmount should: - - Check if cliff period has passed - - Calculate linear vesting based on time passed - - Account for already claimed tokens - - Handle revoked status - -5. claimVestedTokens should: - - Calculate claimable amount - - Update claimed amount - - Transfer tokens - - Emit event - -6. revokeVesting should: - - Only allow admin - - Calculate and transfer unvested tokens back - - Mark schedule as revoked - - Emit event -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/challenge-1-vesting/contracts/TokenVesting.txt b/challenge-1-vesting/contracts/TokenVesting.txt new file mode 100644 index 0000000..6bd2797 --- /dev/null +++ b/challenge-1-vesting/contracts/TokenVesting.txt @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/Pausable.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { + struct VestingSchedule { + uint256 totalAmount; // Total amount of tokens to be vested + uint256 startTime; // Start time of the vesting period + uint256 cliffDuration; // Duration of the cliff period in seconds + uint256 vestingDuration; // Duration of the vesting period in seconds + uint256 amountClaimed; // Amount of tokens already claimed + bool revoked; // Whether the vesting has been revoked + } + + // Token being vested + IERC20 public token; + + // Mapping from beneficiary to vesting schedule + mapping(address => VestingSchedule) public vestingSchedules; + + // Whitelist of beneficiaries + mapping(address => bool) public whitelist; + + // Events + event VestingScheduleCreated(address indexed beneficiary, uint256 amount); + event TokensClaimed(address indexed beneficiary, uint256 amount); + event VestingRevoked(address indexed beneficiary); + event BeneficiaryWhitelisted(address indexed beneficiary); + event BeneficiaryRemovedFromWhitelist(address indexed beneficiary); + + constructor(address tokenAddress) { + require(tokenAddress != address(0), "Token address cannot be zero"); + token = IERC20(tokenAddress); + } + + // Modifier to check if beneficiary is whitelisted + modifier onlyWhitelisted(address beneficiary) { + require(whitelist[beneficiary], "Beneficiary not whitelisted"); + _; + } + + function addToWhitelist(address beneficiary) external onlyOwner { + require(beneficiary != address(0), "Invalid address"); + whitelist[beneficiary] = true; + emit BeneficiaryWhitelisted(beneficiary); + } + + function removeFromWhitelist(address beneficiary) external onlyOwner { + whitelist[beneficiary] = false; + emit BeneficiaryRemovedFromWhitelist(beneficiary); + } + + function createVestingSchedule( + address beneficiary, + uint256 amount, + uint256 cliffDuration, + uint256 vestingDuration, + uint256 startTime + ) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused { + require(beneficiary != address(0), "Beneficiary cannot be zero address"); + require(amount > 0, "Amount must be greater than zero"); + require(vestingDuration > 0, "Vesting duration must be greater than zero"); + require(vestingDuration >= cliffDuration, "Vesting duration must be greater than or equal to cliff duration"); + require(vestingSchedules[beneficiary].totalAmount == 0, "Vesting schedule already exists"); + + // If startTime is 0, use current block timestamp + uint256 start = startTime == 0 ? block.timestamp : startTime; + + // Create new vesting schedule + vestingSchedules[beneficiary] = VestingSchedule({ + totalAmount: amount, + startTime: start, + cliffDuration: cliffDuration, + vestingDuration: vestingDuration, + amountClaimed: 0, + revoked: false + }); + + // Transfer tokens from sender to contract + require(token.transferFrom(msg.sender, address(this), amount), "Token transfer failed"); + + emit VestingScheduleCreated(beneficiary, amount); + } + + function calculateVestedAmount( + address beneficiary + ) public view returns (uint256) { + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + + // If no schedule or revoked, return 0 + if (schedule.totalAmount == 0 || schedule.revoked) { + return 0; + } + + // If current time is before cliff, nothing is vested + if (block.timestamp < schedule.startTime + schedule.cliffDuration) { + return 0; + } + + // If current time is after vesting duration, everything is vested + if (block.timestamp >= schedule.startTime + schedule.vestingDuration) { + return schedule.totalAmount; + } + + // Otherwise, calculate vested amount based on linear vesting + uint256 timeFromStart = block.timestamp - schedule.startTime; + uint256 vestedAmount = (schedule.totalAmount * timeFromStart) / schedule.vestingDuration; + + return vestedAmount; + } + + function claimVestedTokens() external nonReentrant whenNotPaused { + address beneficiary = msg.sender; + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + + require(schedule.totalAmount > 0, "No vesting schedule found"); + require(!schedule.revoked, "Vesting schedule has been revoked"); + + uint256 vestedAmount = calculateVestedAmount(beneficiary); + uint256 claimableAmount = vestedAmount - schedule.amountClaimed; + + require(claimableAmount > 0, "No tokens available to claim"); + + // Update claimed amount + schedule.amountClaimed += claimableAmount; + + // Transfer tokens to beneficiary + require(token.transfer(beneficiary, claimableAmount), "Token transfer failed"); + + emit TokensClaimed(beneficiary, claimableAmount); + } + + function revokeVesting(address beneficiary) external onlyOwner { + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + + require(schedule.totalAmount > 0, "No vesting schedule found"); + require(!schedule.revoked, "Vesting schedule already revoked"); + + // Calculate vested amount + uint256 vestedAmount = calculateVestedAmount(beneficiary); + uint256 claimedAmount = schedule.amountClaimed; + + // Calculate unvested amount to return to owner + uint256 unvestedAmount = schedule.totalAmount - vestedAmount; + + // Mark schedule as revoked + schedule.revoked = true; + + // Transfer unvested tokens back to owner + if (unvestedAmount > 0) { + require(token.transfer(owner(), unvestedAmount), "Token transfer failed"); + } + + emit VestingRevoked(beneficiary); + } + + function pause() external onlyOwner { + _pause(); + } + + function unpause() external onlyOwner { + _unpause(); + } +} \ No newline at end of file diff --git a/challenge-2-yield-farm/contracts/yeild.sol b/challenge-2-yield-farm/contracts/yeild.sol index 421496a..649a0e5 100644 --- a/challenge-2-yield-farm/contracts/yeild.sol +++ b/challenge-2-yield-farm/contracts/yeild.sol @@ -5,72 +5,41 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; -/** - * @title YieldFarm - * @notice Challenge: Implement a yield farming contract with the following requirements: - * - * 1. Users can stake LP tokens and earn reward tokens - * 2. Rewards are distributed based on time and amount staked - * 3. Implement reward boosting mechanism for long-term stakers - * 4. Add emergency withdrawal functionality - * 5. Implement reward rate adjustment mechanism - */ - contract YieldFarm is ReentrancyGuard, Ownable { - // LP token that users can stake IERC20 public lpToken; - - // Token given as reward IERC20 public rewardToken; - - // Reward rate per second uint256 public rewardRate; - - // Last update time uint256 public lastUpdateTime; - - // Reward per token stored uint256 public rewardPerTokenStored; - - // Total staked amount uint256 public totalStaked; - // User struct to track staking info struct UserInfo { - uint256 amount; // Amount of LP tokens staked - uint256 startTime; // Time when user started staking - uint256 rewardDebt; // Reward debt - uint256 pendingRewards; // Unclaimed rewards + uint256 amount; + uint256 startTime; + uint256 rewardDebt; + uint256 pendingRewards; } - // Mapping of user address to their info mapping(address => UserInfo) public userInfo; - // Boost multiplier thresholds (in seconds) uint256 public constant BOOST_THRESHOLD_1 = 7 days; uint256 public constant BOOST_THRESHOLD_2 = 30 days; uint256 public constant BOOST_THRESHOLD_3 = 90 days; - // Events event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardsClaimed(address indexed user, uint256 amount); event EmergencyWithdrawn(address indexed user, uint256 amount); - // TODO: Implement the following functions - - /** - * @notice Initialize the contract with the LP token and reward token addresses - * @param _lpToken Address of the LP token - * @param _rewardToken Address of the reward token - * @param _rewardRate Initial reward rate per second - */ constructor( address _lpToken, address _rewardToken, uint256 _rewardRate ) Ownable(msg.sender) { - // TODO: Initialize contract state + lpToken = IERC20(_lpToken); + rewardToken = IERC20(_rewardToken); + rewardRate = _rewardRate; + lastUpdateTime = block.timestamp; } function updateReward(address _user) internal { @@ -85,101 +54,97 @@ contract YieldFarm is ReentrancyGuard, Ownable { } function rewardPerToken() public view returns (uint256) { - // TODO: Implement pending rewards calculation - // Requirements: - // 1. Calculate rewards since last update - // 2. Apply boost multiplier - // 3. Return total pending rewards + if (totalStaked == 0) return rewardPerTokenStored; + uint256 timeElapsed = block.timestamp - lastUpdateTime; + return rewardPerTokenStored + (timeElapsed * rewardRate * 1e18) / totalStaked; } function earned(address _user) public view returns (uint256) { - // TODO: Implement pending rewards calculation - // Requirements: - // 1. Calculate rewards since last update - // 2. Apply boost multiplier - // 3. Return total pending rewards + UserInfo storage user = userInfo[_user]; + uint256 currentRewardPerToken = rewardPerToken(); + uint256 rewardDifference = currentRewardPerToken - user.rewardDebt; + uint256 newRewards = (user.amount * rewardDifference) / 1e18; + uint256 boost = calculateBoostMultiplier(_user); + return user.pendingRewards + (newRewards * boost) / 100; } - /** - * @notice Stake LP tokens into the farm - * @param _amount Amount of LP tokens to stake - */ function stake(uint256 _amount) external nonReentrant { - // TODO: Implement staking logic - // Requirements: - // 1. Update rewards - // 2. Transfer LP tokens from user - // 3. Update user info and total staked amount - // 4. Emit Staked event + require(_amount > 0, "Cannot stake 0"); + updateReward(msg.sender); + + UserInfo storage user = userInfo[msg.sender]; + lpToken.transferFrom(msg.sender, address(this), _amount); + + if (user.amount == 0) { + user.startTime = block.timestamp; + } + user.amount += _amount; + totalStaked += _amount; + + emit Staked(msg.sender, _amount); } - /** - * @notice Withdraw staked LP tokens - * @param _amount Amount of LP tokens to withdraw - */ function withdraw(uint256 _amount) external nonReentrant { - // TODO: Implement withdrawal logic - // Requirements: - // 1. Update rewards - // 2. Transfer LP tokens to user - // 3. Update user info and total staked amount - // 4. Emit Withdrawn event + UserInfo storage user = userInfo[msg.sender]; + require(user.amount >= _amount, "Insufficient balance"); + updateReward(msg.sender); + + lpToken.transfer(msg.sender, _amount); + user.amount -= _amount; + totalStaked -= _amount; + + if (user.amount == 0) { + user.startTime = 0; + } + + emit Withdrawn(msg.sender, _amount); } - /** - * @notice Claim pending rewards - */ function claimRewards() external nonReentrant { - // TODO: Implement reward claiming logic - // Requirements: - // 1. Calculate pending rewards with boost multiplier - // 2. Transfer rewards to user - // 3. Update user reward debt - // 4. Emit RewardsClaimed event + updateReward(msg.sender); + UserInfo storage user = userInfo[msg.sender]; + + uint256 rewards = user.pendingRewards; + require(rewards > 0, "No rewards to claim"); + + user.pendingRewards = 0; + rewardToken.transfer(msg.sender, rewards); + + emit RewardsClaimed(msg.sender, rewards); } - /** - * @notice Emergency withdraw without caring about rewards - */ function emergencyWithdraw() external nonReentrant { - // TODO: Implement emergency withdrawal - // Requirements: - // 1. Transfer all LP tokens back to user - // 2. Reset user info - // 3. Emit EmergencyWithdrawn event + UserInfo storage user = userInfo[msg.sender]; + uint256 amount = user.amount; + require(amount > 0, "No stake to withdraw"); + + user.amount = 0; + user.startTime = 0; + user.pendingRewards = 0; + user.rewardDebt = 0; + totalStaked -= amount; + + lpToken.transfer(msg.sender, amount); + emit EmergencyWithdrawn(msg.sender, amount); } - /** - * @notice Calculate boost multiplier based on staking duration - * @param _user Address of the user - * @return Boost multiplier (100 = 1x, 150 = 1.5x, etc.) - */ - function calculateBoostMultiplier( - address _user - ) public view returns (uint256) { - // TODO: Implement boost multiplier calculation - // Requirements: - // 1. Calculate staking duration - // 2. Return appropriate multiplier based on duration thresholds + function calculateBoostMultiplier(address _user) public view returns (uint256) { + UserInfo storage user = userInfo[_user]; + if (user.amount == 0) return 100; + + uint256 stakingDuration = block.timestamp - user.startTime; + if (stakingDuration >= BOOST_THRESHOLD_3) return 200; + if (stakingDuration >= BOOST_THRESHOLD_2) return 150; + if (stakingDuration >= BOOST_THRESHOLD_1) return 120; + return 100; } - /** - * @notice Update reward rate - * @param _newRate New reward rate per second - */ function updateRewardRate(uint256 _newRate) external onlyOwner { - // TODO: Implement reward rate update logic - // Requirements: - // 1. Update rewards before changing rate - // 2. Set new reward rate + updateReward(address(0)); + rewardRate = _newRate; } - /** - * @notice View function to see pending rewards for a user - * @param _user Address of the user - * @return Pending reward amount - */ function pendingRewards(address _user) external view returns (uint256) { return earned(_user); } -} +} \ No newline at end of file diff --git a/challenge-3-frontend/app/page.tsx b/challenge-3-frontend/app/page.tsx index fb01185..d042d92 100644 --- a/challenge-3-frontend/app/page.tsx +++ b/challenge-3-frontend/app/page.tsx @@ -1,110 +1,5 @@ -import Image from "next/image"; -import Link from "next/link"; +import { redirect } from "next/navigation"; export default function Home() { - return ( -
-
- OpenGuild logo -

Get started by checking out the demos

-
    -
  1. - Wallet -
  2. -
  3. - Send transaction -
  4. -
  5. - Write contract -
  6. -
  7. - Mint/Redeem LST Bifrost -
  8. -
-
- - Vercel logomark - Deploy now - - - Read our docs - -
-
- -
- ); + return redirect("/yield-farm"); } diff --git a/challenge-3-frontend/app/providers.tsx b/challenge-3-frontend/app/providers.tsx index 91243fe..e1414d7 100644 --- a/challenge-3-frontend/app/providers.tsx +++ b/challenge-3-frontend/app/providers.tsx @@ -20,7 +20,11 @@ import { defineChain } from 'viem'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { WagmiProvider, http, createConfig } from 'wagmi'; import { Provider as JotaiProvider } from 'jotai'; -// import according to docs +import { + LP_ADDRESS, + REWARD_ADDRESS, + YIELD_FARM_ADDRESS, +} from "@/lib/config"; export const westendAssetHub = defineChain({ id: 420420421, @@ -40,9 +44,14 @@ export const westendAssetHub = defineChain({ default: { name: 'Explorer', url: 'https://assethub-westend.subscan.io' }, }, contracts: { - multicall3: { - address: '0x5545dec97cb957e83d3e6a1e82fabfacf9764cf1', - blockCreated: 10174702, + lpToken: { + address: LP_ADDRESS, + }, + rewardToken: { + address: REWARD_ADDRESS, + }, + yieldToken: { + address: YIELD_FARM_ADDRESS, }, }, }) @@ -67,7 +76,7 @@ const { wallets } = getDefaultWallets(); // initialize and destructure wallets object const config = getDefaultConfig({ - appName: "DOTUI", // Name your app + appName: "OpenGuild", // Name your app projectId: "ddf8cf3ee0013535c3760d4c79c9c8b9", // Enter your WalletConnect Project ID here wallets: [ ...wallets, diff --git a/challenge-3-frontend/app/vesting/page.tsx b/challenge-3-frontend/app/vesting/page.tsx new file mode 100644 index 0000000..fd8090a --- /dev/null +++ b/challenge-3-frontend/app/vesting/page.tsx @@ -0,0 +1,15 @@ +"use client"; +import Navbar from "@/components/navbar"; +import SigpassKit from "@/components/sigpasskit"; +import Vesting from "@/components/vesting"; + +export default function VestingPage() { + return ( +
+ + +

Vesting

+ +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/app/yield-farm/loader.tsx b/challenge-3-frontend/app/yield-farm/loader.tsx new file mode 100644 index 0000000..e288aea --- /dev/null +++ b/challenge-3-frontend/app/yield-farm/loader.tsx @@ -0,0 +1,17 @@ +import { Skeleton } from "@/components/ui/skeleton" + +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return ( +
+ +
+ + + + +
+ +
+ ) +} \ No newline at end of file diff --git a/challenge-3-frontend/app/yield-farm/page.tsx b/challenge-3-frontend/app/yield-farm/page.tsx new file mode 100644 index 0000000..adc6f4b --- /dev/null +++ b/challenge-3-frontend/app/yield-farm/page.tsx @@ -0,0 +1,14 @@ +import Navbar from "@/components/navbar"; +import SigpassKit from "@/components/sigpasskit"; +import YieldFarm from "@/components/yield-farm"; + +export default function YieldFarmPage() { + return ( +
+ + +

Yield Farming

+ +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/mint-mock-token.tsx b/challenge-3-frontend/components/mint-mock-token.tsx new file mode 100644 index 0000000..4dcddcf --- /dev/null +++ b/challenge-3-frontend/components/mint-mock-token.tsx @@ -0,0 +1,102 @@ +"use client"; + +import { useEffect } from "react"; +import { + useWaitForTransactionReceipt, + useConfig, + useWriteContract, + useAccount, + useReadContract, +} from "wagmi"; +import { parseUnits } from "viem"; +import { Loader2 } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { getSigpassWallet } from "@/lib/sigpass"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { localConfig, westendAssetHub } from "@/app/providers"; +import { LP_ADDRESS } from "@/lib/config"; +import { mockErc20Abi } from "@/lib/abi"; +type Props = { + label: string; +}; +export default function MintMockToken({ label }: Props) { + + const config = useConfig(); + const account = useAccount(); + const address = useAtomValue(addressAtom); + const { + data: hash, + isPending, + writeContractAsync, + } = useWriteContract({ + config: address ? localConfig : config, + }); + + const { data, refetch } = useReadContract({ + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "decimals", + chainId: westendAssetHub.id, + config: address ? localConfig : config, + }); + + // get the max balance and decimals from the data + const decimals = data as number | undefined; + + // useWaitForTransactionReceipt hook to wait for transaction receipt + const { isLoading: isConfirming, isSuccess: isConfirmed } = + useWaitForTransactionReceipt({ + hash, + config: address ? localConfig : config, + }); + + const handleMintToken = async () => { + try { + if (address) { + writeContractAsync({ + account: await getSigpassWallet(), + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "mint", + args: [ + address ? address : account.address, + parseUnits("1000", decimals as number), + ], + chainId: westendAssetHub.id, + }); + } else { + writeContractAsync({ + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "mint", + args: [ + address ? address : account.address, + parseUnits("1000", decimals as number), + ], + chainId: westendAssetHub.id, + }); + } + } catch (error) { + console.error(error); + } + }; + + // when isConfirmed, refetch the balance of the address + useEffect(() => { + if (isConfirmed) { + refetch(); + } + }, [isConfirmed, refetch]); + + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/navbar.tsx b/challenge-3-frontend/components/navbar.tsx index d212169..64b16fe 100644 --- a/challenge-3-frontend/components/navbar.tsx +++ b/challenge-3-frontend/components/navbar.tsx @@ -1,32 +1,47 @@ +"use client"; + import Link from "next/link"; +import { usePathname } from "next/navigation"; export default function Navbar() { + const pathname = usePathname(); + return ( -
- - Home - - - Wallet - - - Send transaction - - - Write contract - - - Mint/Redeem LST Bifrost - +
+ +
+ + Home + + + Wallet + + + Send transaction + + + Write contract + + + Mint/Redeem LST Bifrost + + + + Vesting + + + Yield Farm + +
); } diff --git a/challenge-3-frontend/components/stake.tsx b/challenge-3-frontend/components/stake.tsx new file mode 100644 index 0000000..64bab77 --- /dev/null +++ b/challenge-3-frontend/components/stake.tsx @@ -0,0 +1,439 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { + type BaseError, + useWaitForTransactionReceipt, + useConfig, + useWriteContract, + useReadContracts, + useAccount, +} from "wagmi"; +import { parseUnits, formatUnits } from "viem"; +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, + WalletMinimal, +} from "lucide-react"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { truncateHash } from "@/lib/utils"; +import CopyButton from "@/components/copy-button"; +import { getSigpassWallet } from "@/lib/sigpass"; +import { westendAssetHub } from "@/app/providers"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { Skeleton } from "./ui/skeleton"; +import { localConfig } from "@/app/providers"; +import { mockErc20Abi, yieldFarmingAbi } from "@/lib/abi"; +import { + LP_ADDRESS, + YIELD_FARM_ADDRESS, +} from "@/lib/config"; +import MintMockToken from "./mint-mock-token"; + +export default function Stake() { + const config = useConfig(); + const account = useAccount(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const address = useAtomValue(addressAtom); + const formSchema = z.object({ + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,18}$/.test(val), { + message: "Amount cannot have more than 18 decimal places", + }) + .superRefine((val, ctx) => { + if (!maxBalance || !decimals) return; + + const inputAmount = parseUnits(val, decimals as number); + + if (inputAmount > (maxBalance as bigint)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Amount exceeds available balance", + }); + } + }), + }); + + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + amount: "", + }, + }); + + const { + data: hash, + error, + isPending, + writeContractAsync, + } = useWriteContract({ + config: address ? localConfig : config, + }); + + const { data, refetch } = useReadContracts({ + contracts: [ + { + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "balanceOf", + args: [address ? address : account.address], + }, + { + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "decimals", + }, + { + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "allowance", + args: [address ? address : account.address, YIELD_FARM_ADDRESS], + }, + ], + config: address ? localConfig : config, + }); + + + const maxBalance = data?.[0]?.result as bigint | undefined; + const decimals = data?.[1]?.result as number | undefined; + const mintAllowance = data?.[2]?.result as bigint | undefined; + const amount = form.watch("amount"); + + const needsApprove = + mintAllowance !== undefined && amount + ? mintAllowance < parseUnits(amount, decimals || 18) + : false; + + async function onSubmit(values: z.infer) { + if (address) { + if (needsApprove) { + writeContractAsync({ + account: await getSigpassWallet(), + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "approve", + args: [ + YIELD_FARM_ADDRESS, + parseUnits(values.amount, decimals as number), + ], + chainId: westendAssetHub.id, + }); + } else { + writeContractAsync({ + account: await getSigpassWallet(), + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "stake", + args: [parseUnits(values.amount, decimals as number)], + chainId: westendAssetHub.id, + }); + } + } else { + + if (needsApprove) { + writeContractAsync({ + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "approve", + args: [ + YIELD_FARM_ADDRESS, + parseUnits(values.amount, decimals as number), + ], + chainId: westendAssetHub.id, + }); + } else { + writeContractAsync({ + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "stake", + args: [parseUnits(values.amount, decimals as number)], + chainId: westendAssetHub.id, + }); + } + } + } + + useEffect(() => { + if (hash) { + setOpen(true); + } + }, [hash]); + + const { isLoading: isConfirming, isSuccess: isConfirmed } = + useWaitForTransactionReceipt({ + hash, + config: address ? localConfig : config, + }); + + useEffect(() => { + if (isConfirmed) { + refetch(); + } + }, [isConfirmed, refetch]); + + return ( +
+ +
+ + ( + +
+ Amount to stake +
+ {" "} + {maxBalance ? ( + formatUnits(maxBalance as bigint, decimals as number) + ) : ( + + )}{" "} + LP Token +
+
+ + {isDesktop ? ( + + ) : ( + + )} + + + The amount of LPToken to stake + + +
+ )} + /> +
+ {isPending ? ( + + ) : needsApprove ? ( + + ) : ( + + )} + {isPending ? ( + + ) : needsApprove ? ( + + ) : ( + + )} +
+ + + { + // Desktop would be using dialog + isDesktop ? ( + + + + + + + Transaction status + + + Follow the transaction status below. + +
+ {hash ? ( +
+ + Transaction Hash + + {truncateHash(hash)} + + + +
+ ) : ( +
+ + No transaction hash +
+ )} + {!isPending && !isConfirmed && !isConfirming && ( +
+ No transaction submitted +
+ )} + {isConfirming && ( +
+ Waiting + for confirmation... +
+ )} + {isConfirmed && ( +
+ Transaction confirmed! +
+ )} + {error && ( +
+ Error:{" "} + {(error as BaseError).shortMessage || error.message} +
+ )} +
+ + + + + +
+
+ ) : ( + // Mobile would be using drawer + + + + + + + Transaction status + + Follow the transaction status below. + + +
+ {hash ? ( +
+ + Transaction Hash + + {truncateHash(hash)} + + + +
+ ) : ( +
+ + No transaction hash +
+ )} + {!isPending && !isConfirmed && !isConfirming && ( +
+ No transaction submitted +
+ )} + {isConfirming && ( +
+ Waiting + for confirmation... +
+ )} + {isConfirmed && ( +
+ Transaction confirmed! +
+ )} + {error && ( +
+ Error:{" "} + {(error as BaseError).shortMessage || error.message} +
+ )} +
+ + + + + +
+
+ ) + } +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/vesting.tsx b/challenge-3-frontend/components/vesting.tsx new file mode 100644 index 0000000..811b200 --- /dev/null +++ b/challenge-3-frontend/components/vesting.tsx @@ -0,0 +1,243 @@ +"use client"; + +import { useState } from "react"; +import { + useConfig, + useWriteContract, + useReadContracts, + useAccount, + useWaitForTransactionReceipt, +} from "wagmi"; +import { parseUnits, formatUnits } from "viem"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { Skeleton } from "./ui/skeleton"; +import { vestingAbi } from "@/lib/abi"; +import { VESTING_ADDRESS } from "@/lib//config"; + +const formSchema = z.object({ + beneficiary: z.string().startsWith("0x"), + amount: z.string().refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }), + startTime: z.string().refine((val) => !isNaN(parseInt(val)), { + message: "Start time must be a valid timestamp", + }), + cliff: z.string().refine((val) => !isNaN(parseInt(val)) && parseInt(val) >= 0, { + message: "Cliff must be a non-negative number", + }), + duration: z.string().refine((val) => !isNaN(parseInt(val)) && parseInt(val) > 0, { + message: "Duration must be greater than 0", + }), +}); + +export default function Vesting() { + const config = useConfig(); + const account = useAccount(); + const address = useAtomValue(addressAtom); + const [isCreating, setIsCreating] = useState(false); + const [isClaiming, setIsClaiming] = useState(false); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + beneficiary: "", + amount: "", + startTime: Math.floor(Date.now() / 1000).toString(), + cliff: "0", + duration: "0", + }, + }); + + const { writeContractAsync } = useWriteContract({ + config: config, + }); + + const { data: vestingSchedule, isLoading: isLoadingSchedule } = useReadContracts({ + contracts: [ + { + address: VESTING_ADDRESS, + abi: vestingAbi, + functionName: "getVestingSchedule", + args: [account.address || "0x0000000000000000000000000000000000000000"], + } + ], + }); + + async function onSubmit(values: z.infer) { + try { + setIsCreating(true); + const tx = await writeContractAsync({ + address: VESTING_ADDRESS, + abi: vestingAbi, + functionName: 'createVestingSchedule', + args: [ + values.beneficiary as `0x${string}`, + parseUnits(values.amount, 18), + BigInt(values.startTime), + BigInt(values.cliff), + BigInt(values.duration), + ], + }); + + const receipt = await useWaitForTransactionReceipt({ + hash: tx, + }); + + form.reset(); + } catch (error) { + console.error('Error creating vesting schedule:', error); + } finally { + setIsCreating(false); + } + } + + const handleClaim = async () => { + try { + setIsClaiming(true); + const tx = await writeContractAsync({ + address: VESTING_ADDRESS, + abi: vestingAbi, + functionName: 'release', + args: [address as `0x${string}`], + }); + + await useWaitForTransactionReceipt({ + hash: tx, + }); + } catch (error) { + console.error('Error claiming tokens:', error); + } finally { + setIsClaiming(false); + } + }; + + const schedule = vestingSchedule?.[0]?.result; + + return ( +
+
+

Create Vesting Schedule

+
+ + ( + + Beneficiary Address + + + + + + )} + /> + ( + + Amount + + + + + + )} + /> + ( + + Start Time (Unix Timestamp) + + + + + + )} + /> + ( + + Cliff (seconds) + + + + + + )} + /> + ( + + Duration (seconds) + + + + + + )} + /> + + + +
+ +
+

Your Vesting Schedule

+ {isLoadingSchedule ? ( +
+ + + + + +
+ ) : schedule ? ( +
+

Total Amount: {formatUnits(schedule.totalAmount, 18)} tokens

+

Start Time: {new Date(Number(schedule.startTime) * 1000).toLocaleString()}

+

Cliff: {Number(schedule.cliff)} seconds

+

Duration: {Number(schedule.duration)} seconds

+

Released Amount: {formatUnits(schedule.releasedAmount, 18)} tokens

+

Status: {schedule.revoked ? 'Revoked' : 'Active'}

+ {!schedule.revoked && ( + + )} +
+ ) : ( +
+

No vesting schedule found

+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/withdraw.tsx b/challenge-3-frontend/components/withdraw.tsx new file mode 100644 index 0000000..8be1ab5 --- /dev/null +++ b/challenge-3-frontend/components/withdraw.tsx @@ -0,0 +1,434 @@ +"use client"; + +// React imports +import { useState, useEffect } from "react"; + +// Wagmi imports +import { + type BaseError, + useWaitForTransactionReceipt, + useConfig, + useWriteContract, + useReadContracts, + useAccount, +} from "wagmi"; + +// Viem imports +import { parseUnits, formatUnits } from "viem"; + +// Lucide imports (for icons) +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, + WalletMinimal, +} from "lucide-react"; + +// Zod imports +import { z } from "zod"; + +// Zod resolver imports +import { zodResolver } from "@hookform/resolvers/zod"; + +// React hook form imports +import { useForm } from "react-hook-form"; + +// UI imports +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; + +// Utils imports +import { truncateHash } from "@/lib/utils"; + +// Component imports +import CopyButton from "@/components/copy-button"; + +// Library imports +import { getSigpassWallet } from "@/lib/sigpass"; +import { westendAssetHub } from "@/app/providers"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { Skeleton } from "./ui/skeleton"; +import { localConfig } from "@/app/providers"; +import { mockErc20Abi, yieldFarmingAbi } from "@/lib/abi"; +import { + LP_ADDRESS, + YIELD_FARM_ADDRESS, +} from "@/lib/config"; + +export default function Withdraw() { + const config = useConfig(); + const account = useAccount(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const address = useAtomValue(addressAtom); + const formSchema = z.object({ + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,18}$/.test(val), { + message: "Amount cannot have more than 18 decimal places", + }) + .superRefine((val, ctx) => { + if (!maxBalance || !decimals) return; + + const inputAmount = parseUnits(val, decimals as number); + + if (inputAmount > (maxBalance as bigint)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Amount exceeds available balance", + }); + } + }), + }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + amount: "", + }, + }); + + const { + data: hash, + error, + isPending, + writeContractAsync, + } = useWriteContract({ + config: address ? localConfig : config, + }); + + const { data, refetch } = useReadContracts({ + contracts: [ + { + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "userInfo", + args: [address ? address : account.address], + }, + { + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "pendingRewards", + args: [address ? address : account.address], + }, + { + address: LP_ADDRESS, + abi: mockErc20Abi, + functionName: "decimals", + }, + ], + config: address ? localConfig : config, + }); + + const maxBalance = (data?.[0]?.result as [bigint] | undefined)?.[0]; + const pendingRewards = data?.[1]?.result as bigint | undefined; + const decimals = data?.[2]?.result as number | undefined; + + async function onSubmit(values: z.infer) { + if (address) { + writeContractAsync({ + account: await getSigpassWallet(), + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "withdraw", + args: [parseUnits(values.amount, decimals as number)], + chainId: westendAssetHub.id, + }); + } else { + writeContractAsync({ + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "withdraw", + args: [parseUnits(values.amount, decimals as number)], + chainId: westendAssetHub.id, + }); + } + } + + const handleClaim = async () => { + if (address) { + writeContractAsync({ + account: await getSigpassWallet(), + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "claimRewards", + chainId: westendAssetHub.id, + }); + } else { + writeContractAsync({ + address: YIELD_FARM_ADDRESS, + abi: yieldFarmingAbi, + functionName: "claimRewards", + chainId: westendAssetHub.id, + }); + } + }; + + useEffect(() => { + if (hash) { + setOpen(true); + } + }, [hash]); + + const { isLoading: isConfirming, isSuccess: isConfirmed } = + useWaitForTransactionReceipt({ + hash, + config: address ? localConfig : config, + }); + + useEffect(() => { + if (isConfirmed) { + refetch(); + } + }, [isConfirmed, refetch]); + + return ( +
+ {pendingRewards && pendingRewards > 0 ? ( + <> + + Total reward:{" "} + {formatUnits(pendingRewards as bigint, decimals as number)} + + + + ) : null} +
+ + ( + +
+ Amount to unstake +
+ {" "} + {maxBalance ? ( + formatUnits(maxBalance as bigint, decimals as number) + ) : ( + + )}{" "} + LP Token +
+
+ + {isDesktop ? ( + + ) : ( + + )} + + + The amount of LPToken to unstake + + +
+ )} + /> +
+ {isPending ? ( + + ) : ( + + )} +
+ + + { + // Desktop would be using dialog + isDesktop ? ( + + + + + + + Transaction status + + + Follow the transaction status below. + +
+ {hash ? ( +
+ + Transaction Hash + + {truncateHash(hash)} + + + +
+ ) : ( +
+ + No transaction hash +
+ )} + {!isPending && !isConfirmed && !isConfirming && ( +
+ No transaction submitted +
+ )} + {isConfirming && ( +
+ Waiting + for confirmation... +
+ )} + {isConfirmed && ( +
+ Transaction confirmed! +
+ )} + {error && ( +
+ Error:{" "} + {(error as BaseError).shortMessage || error.message} +
+ )} +
+ + + + + +
+
+ ) : ( + // Mobile would be using drawer + + + + + + + Transaction status + + Follow the transaction status below. + + +
+ {hash ? ( +
+ + Transaction Hash + + {truncateHash(hash)} + + + +
+ ) : ( +
+ + No transaction hash +
+ )} + {!isPending && !isConfirmed && !isConfirming && ( +
+ No transaction submitted +
+ )} + {isConfirming && ( +
+ Waiting + for confirmation... +
+ )} + {isConfirmed && ( +
+ Transaction confirmed! +
+ )} + {error && ( +
+ Error:{" "} + {(error as BaseError).shortMessage || error.message} +
+ )} +
+ + + + + +
+
+ ) + } +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/yield-farm.tsx b/challenge-3-frontend/components/yield-farm.tsx new file mode 100644 index 0000000..fec621c --- /dev/null +++ b/challenge-3-frontend/components/yield-farm.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; +import Stake from "./stake"; +import Withdraw from "./withdraw"; + +export default function YieldFarm() { + return ( +
+ + + Stake + Withdraw + + + + + + + + +
+ ); +} \ No newline at end of file diff --git a/challenge-3-frontend/lib/abi.ts b/challenge-3-frontend/lib/abi.ts index 78ac757..c52f4b0 100644 --- a/challenge-3-frontend/lib/abi.ts +++ b/challenge-3-frontend/lib/abi.ts @@ -1,2419 +1,3415 @@ -// ERC-20 token ABI + export const erc20Abi = [ - { - inputs: [ - { - internalType: "address", - name: "initialOwner", - type: "address", - }, - ], - stateMutability: "nonpayable", - type: "constructor", - }, - { - inputs: [], - name: "ECDSAInvalidSignature", - type: "error", - }, - { - inputs: [ - { - internalType: "uint256", - name: "length", - type: "uint256", - }, - ], - name: "ECDSAInvalidSignatureLength", - type: "error", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "s", - type: "bytes32", - }, - ], - name: "ECDSAInvalidSignatureS", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "allowance", - type: "uint256", - }, - { - internalType: "uint256", - name: "needed", - type: "uint256", - }, - ], - name: "ERC20InsufficientAllowance", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address", - }, - { - internalType: "uint256", - name: "balance", - type: "uint256", - }, - { - internalType: "uint256", - name: "needed", - type: "uint256", - }, - ], - name: "ERC20InsufficientBalance", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "approver", - type: "address", - }, - ], - name: "ERC20InvalidApprover", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "receiver", - type: "address", - }, - ], - name: "ERC20InvalidReceiver", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address", - }, - ], - name: "ERC20InvalidSender", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - ], - name: "ERC20InvalidSpender", - type: "error", - }, - { - inputs: [ - { - internalType: "uint256", - name: "deadline", - type: "uint256", - }, - ], - name: "ERC2612ExpiredSignature", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "signer", - type: "address", - }, - { - internalType: "address", - name: "owner", - type: "address", - }, - ], - name: "ERC2612InvalidSigner", - type: "error", - }, - { - inputs: [ - { - internalType: "uint256", - name: "maxLoan", - type: "uint256", - }, - ], - name: "ERC3156ExceededMaxLoan", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "receiver", - type: "address", - }, - ], - name: "ERC3156InvalidReceiver", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "token", - type: "address", - }, - ], - name: "ERC3156UnsupportedToken", - type: "error", - }, - { - inputs: [], - name: "EnforcedPause", - type: "error", - }, - { - inputs: [], - name: "ExpectedPause", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address", - }, - { - internalType: "uint256", - name: "currentNonce", - type: "uint256", - }, - ], - name: "InvalidAccountNonce", - type: "error", - }, - { - inputs: [], - name: "InvalidShortString", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - ], - name: "OwnableInvalidOwner", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address", - }, - ], - name: "OwnableUnauthorizedAccount", - type: "error", - }, - { - inputs: [ - { - internalType: "string", - name: "str", - type: "string", - }, - ], - name: "StringTooLong", - type: "error", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "owner", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "spender", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "Approval", - type: "event", - }, - { - anonymous: false, - inputs: [], - name: "EIP712DomainChanged", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "previousOwner", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "newOwner", - type: "address", - }, - ], - name: "OwnershipTransferred", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "address", - name: "account", - type: "address", - }, - ], - name: "Paused", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "from", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "to", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "Transfer", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "address", - name: "account", - type: "address", - }, - ], - name: "Unpaused", - type: "event", - }, - { - inputs: [], - name: "DOMAIN_SEPARATOR", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - { - internalType: "address", - name: "spender", - type: "address", - }, - ], - name: "allowance", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "approve", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address", - }, - ], - name: "balanceOf", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "burn", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "burnFrom", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "decimals", - outputs: [ - { - internalType: "uint8", - name: "", - type: "uint8", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "eip712Domain", - outputs: [ - { - internalType: "bytes1", - name: "fields", - type: "bytes1", - }, - { - internalType: "string", - name: "name", - type: "string", - }, - { - internalType: "string", - name: "version", - type: "string", - }, - { - internalType: "uint256", - name: "chainId", - type: "uint256", - }, - { - internalType: "address", - name: "verifyingContract", - type: "address", - }, - { - internalType: "bytes32", - name: "salt", - type: "bytes32", - }, - { - internalType: "uint256[]", - name: "extensions", - type: "uint256[]", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "token", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "flashFee", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "contract IERC3156FlashBorrower", - name: "receiver", - type: "address", - }, - { - internalType: "address", - name: "token", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - { - internalType: "bytes", - name: "data", - type: "bytes", - }, - ], - name: "flashLoan", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "token", - type: "address", - }, - ], - name: "maxFlashLoan", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "to", - type: "address", - }, - { - internalType: "uint256", - name: "amount", - type: "uint256", - }, - ], - name: "mint", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "name", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - ], - name: "nonces", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "pause", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "paused", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - { - internalType: "uint256", - name: "deadline", - type: "uint256", - }, - { - internalType: "uint8", - name: "v", - type: "uint8", - }, - { - internalType: "bytes32", - name: "r", - type: "bytes32", - }, - { - internalType: "bytes32", - name: "s", - type: "bytes32", - }, - ], - name: "permit", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "renounceOwnership", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "symbol", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "totalSupply", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "to", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "from", - type: "address", - }, - { - internalType: "address", - name: "to", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "transferFrom", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "newOwner", - type: "address", - }, - ], - name: "transferOwnership", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "unpause", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, + { + inputs: [ + { + internalType: "address", + name: "initialOwner", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "ECDSAInvalidSignature", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "length", + type: "uint256", + }, + ], + name: "ECDSAInvalidSignatureLength", + type: "error", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "ECDSAInvalidSignatureS", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "ERC20InvalidSpender", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + ], + name: "ERC2612ExpiredSignature", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "signer", + type: "address", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "ERC2612InvalidSigner", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "maxLoan", + type: "uint256", + }, + ], + name: "ERC3156ExceededMaxLoan", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC3156InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "ERC3156UnsupportedToken", + type: "error", + }, + { + inputs: [], + name: "EnforcedPause", + type: "error", + }, + { + inputs: [], + name: "ExpectedPause", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "currentNonce", + type: "uint256", + }, + ], + name: "InvalidAccountNonce", + type: "error", + }, + { + inputs: [], + name: "InvalidShortString", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + inputs: [ + { + internalType: "string", + name: "str", + type: "string", + }, + ], + name: "StringTooLong", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [], + name: "EIP712DomainChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "burnFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { + internalType: "bytes1", + name: "fields", + type: "bytes1", + }, + { + internalType: "string", + name: "name", + type: "string", + }, + { + internalType: "string", + name: "version", + type: "string", + }, + { + internalType: "uint256", + name: "chainId", + type: "uint256", + }, + { + internalType: "address", + name: "verifyingContract", + type: "address", + }, + { + internalType: "bytes32", + name: "salt", + type: "bytes32", + }, + { + internalType: "uint256[]", + name: "extensions", + type: "uint256[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "flashFee", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC3156FlashBorrower", + name: "receiver", + type: "address", + }, + { + internalType: "address", + name: "token", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "flashLoan", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "maxFlashLoan", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "nonces", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; -// ERC-20 token ABI Extend export const erc20AbiExtend = [ - { - "inputs": [ - { - "internalType": "address", - "name": "initialOwner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC20InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC20InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC20InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "ERC20InvalidSpender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "ERC2612ExpiredSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "signer", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "ERC2612InvalidSigner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxLoan", - "type": "uint256" - } - ], - "name": "ERC3156ExceededMaxLoan", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC3156InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "ERC3156UnsupportedToken", - "type": "error" - }, - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "currentNonce", - "type": "uint256" - } - ], - "name": "InvalidAccountNonce", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidShortString", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "str", - "type": "string" - } - ], - "name": "StringTooLong", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "EIP712DomainChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eip712Domain", - "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "verifyingContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "flashFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC3156FlashBorrower", - "name": "receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "flashLoan", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "maxFlashLoan", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } + { + inputs: [ + { + internalType: "address", + name: "initialOwner", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "ECDSAInvalidSignature", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "length", + type: "uint256", + }, + ], + name: "ECDSAInvalidSignatureLength", + type: "error", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "ECDSAInvalidSignatureS", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "ERC20InvalidSpender", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + ], + name: "ERC2612ExpiredSignature", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "signer", + type: "address", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "ERC2612InvalidSigner", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "maxLoan", + type: "uint256", + }, + ], + name: "ERC3156ExceededMaxLoan", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC3156InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "ERC3156UnsupportedToken", + type: "error", + }, + { + inputs: [], + name: "EnforcedPause", + type: "error", + }, + { + inputs: [], + name: "ExpectedPause", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "currentNonce", + type: "uint256", + }, + ], + name: "InvalidAccountNonce", + type: "error", + }, + { + inputs: [], + name: "InvalidShortString", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + inputs: [ + { + internalType: "string", + name: "str", + type: "string", + }, + ], + name: "StringTooLong", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [], + name: "EIP712DomainChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "burnFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { + internalType: "bytes1", + name: "fields", + type: "bytes1", + }, + { + internalType: "string", + name: "name", + type: "string", + }, + { + internalType: "string", + name: "version", + type: "string", + }, + { + internalType: "uint256", + name: "chainId", + type: "uint256", + }, + { + internalType: "address", + name: "verifyingContract", + type: "address", + }, + { + internalType: "bytes32", + name: "salt", + type: "bytes32", + }, + { + internalType: "uint256[]", + name: "extensions", + type: "uint256[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "flashFee", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC3156FlashBorrower", + name: "receiver", + type: "address", + }, + { + internalType: "address", + name: "token", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "flashLoan", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "maxFlashLoan", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "nonces", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; -// Moonbeam SLpX ABI Contract export const moonbeamSlpxAbi = [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "admin_", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ - { - "internalType": "address", - "name": "implementation_", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "amount", - "type": "uint128" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "dest_chain_id", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "receiver", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "string", - "name": "remark", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "channel_id", - "type": "uint32" - } - ], - "name": "CreateOrder", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "callcode", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "string", - "name": "remark", - "type": "string" - } - ], - "name": "Mint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "redeemer", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "callcode", - "type": "bytes" - } - ], - "name": "Redeem", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "BNCAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "addressToAssetInfo", - "outputs": [ - { - "internalType": "bytes2", - "name": "currencyId", - "type": "bytes2" - }, - { - "internalType": "uint256", - "name": "operationalMin", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bifrostParaId", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint128", - "name": "amount", - "type": "uint128" - }, - { - "internalType": "uint64", - "name": "dest_chain_id", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "receiver", - "type": "bytes" - }, - { - "internalType": "string", - "name": "remark", - "type": "string" - }, - { - "internalType": "uint32", - "name": "channel_id", - "type": "uint32" - } - ], - "name": "create_order", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "destChainInfo", - "outputs": [ - { - "internalType": "bool", - "name": "is_evm", - "type": "bool" - }, - { - "internalType": "bool", - "name": "is_substrate", - "type": "bool" - }, - { - "internalType": "bytes1", - "name": "raw_chain_index", - "type": "bytes1" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_BNCAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_bifrostParaId", - "type": "uint32" - }, - { - "internalType": "bytes2", - "name": "_nativeCurrencyId", - "type": "bytes2" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "string", - "name": "remark", - "type": "string" - } - ], - "name": "mintVAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "string", - "name": "remark", - "type": "string" - }, - { - "internalType": "uint32", - "name": "channel_id", - "type": "uint32" - } - ], - "name": "mintVAssetWithChannelId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "string", - "name": "remark", - "type": "string" - } - ], - "name": "mintVNativeAsset", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "string", - "name": "remark", - "type": "string" - }, - { - "internalType": "uint32", - "name": "channel_id", - "type": "uint32" - } - ], - "name": "mintVNativeAssetWithChannelId", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum MoonbeamSlpx.Operation", - "name": "", - "type": "uint8" - } - ], - "name": "operationToFeeInfo", - "outputs": [ - { - "internalType": "uint64", - "name": "transactRequiredWeightAtMost", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "feeAmount", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "overallWeight", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vAssetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeemAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "bytes2", - "name": "currencyId", - "type": "bytes2" - }, - { - "internalType": "uint256", - "name": "minimumValue", - "type": "uint256" - } - ], - "name": "setAssetAddressInfo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "dest_chain_id", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "is_evm", - "type": "bool" - }, - { - "internalType": "bool", - "name": "is_substrate", - "type": "bool" - }, - { - "internalType": "bytes1", - "name": "raw_chain_index", - "type": "bytes1" - } - ], - "name": "setDestChainInfo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum MoonbeamSlpx.Operation", - "name": "_operation", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "_transactRequiredWeightAtMost", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "_overallWeight", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "_feeAmount", - "type": "uint256" - } - ], - "name": "setOperationToFeeInfo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - } -]; \ No newline at end of file + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "previousAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "AdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "beacon", + type: "address", + }, + ], + name: "BeaconUpgraded", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "implementation", + type: "address", + }, + ], + name: "Upgraded", + type: "event", + }, + { + stateMutability: "payable", + type: "fallback", + }, + { + inputs: [], + name: "admin", + outputs: [ + { + internalType: "address", + name: "admin_", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "changeAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "implementation", + outputs: [ + { + internalType: "address", + name: "implementation_", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newImplementation", + type: "address", + }, + ], + name: "upgradeTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newImplementation", + type: "address", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "upgradeToAndCall", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + stateMutability: "payable", + type: "receive", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + indexed: false, + internalType: "uint128", + name: "amount", + type: "uint128", + }, + { + indexed: false, + internalType: "uint64", + name: "dest_chain_id", + type: "uint64", + }, + { + indexed: false, + internalType: "bytes", + name: "receiver", + type: "bytes", + }, + { + indexed: false, + internalType: "string", + name: "remark", + type: "string", + }, + { + indexed: false, + internalType: "uint32", + name: "channel_id", + type: "uint32", + }, + ], + name: "CreateOrder", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint8", + name: "version", + type: "uint8", + }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "minter", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "receiver", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "callcode", + type: "bytes", + }, + { + indexed: false, + internalType: "string", + name: "remark", + type: "string", + }, + ], + name: "Mint", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "redeemer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "receiver", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "callcode", + type: "bytes", + }, + ], + name: "Redeem", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [], + name: "BNCAddress", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "addressToAssetInfo", + outputs: [ + { + internalType: "bytes2", + name: "currencyId", + type: "bytes2", + }, + { + internalType: "uint256", + name: "operationalMin", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "bifrostParaId", + outputs: [ + { + internalType: "uint32", + name: "", + type: "uint32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + internalType: "uint128", + name: "amount", + type: "uint128", + }, + { + internalType: "uint64", + name: "dest_chain_id", + type: "uint64", + }, + { + internalType: "bytes", + name: "receiver", + type: "bytes", + }, + { + internalType: "string", + name: "remark", + type: "string", + }, + { + internalType: "uint32", + name: "channel_id", + type: "uint32", + }, + ], + name: "create_order", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint64", + name: "", + type: "uint64", + }, + ], + name: "destChainInfo", + outputs: [ + { + internalType: "bool", + name: "is_evm", + type: "bool", + }, + { + internalType: "bool", + name: "is_substrate", + type: "bool", + }, + { + internalType: "bytes1", + name: "raw_chain_index", + type: "bytes1", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_BNCAddress", + type: "address", + }, + { + internalType: "uint32", + name: "_bifrostParaId", + type: "uint32", + }, + { + internalType: "bytes2", + name: "_nativeCurrencyId", + type: "bytes2", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + internalType: "address", + name: "receiver", + type: "address", + }, + { + internalType: "string", + name: "remark", + type: "string", + }, + ], + name: "mintVAsset", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + internalType: "address", + name: "receiver", + type: "address", + }, + { + internalType: "string", + name: "remark", + type: "string", + }, + { + internalType: "uint32", + name: "channel_id", + type: "uint32", + }, + ], + name: "mintVAssetWithChannelId", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + { + internalType: "string", + name: "remark", + type: "string", + }, + ], + name: "mintVNativeAsset", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + { + internalType: "string", + name: "remark", + type: "string", + }, + { + internalType: "uint32", + name: "channel_id", + type: "uint32", + }, + ], + name: "mintVNativeAssetWithChannelId", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "enum MoonbeamSlpx.Operation", + name: "", + type: "uint8", + }, + ], + name: "operationToFeeInfo", + outputs: [ + { + internalType: "uint64", + name: "transactRequiredWeightAtMost", + type: "uint64", + }, + { + internalType: "uint256", + name: "feeAmount", + type: "uint256", + }, + { + internalType: "uint64", + name: "overallWeight", + type: "uint64", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "vAssetAddress", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "redeemAsset", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "assetAddress", + type: "address", + }, + { + internalType: "bytes2", + name: "currencyId", + type: "bytes2", + }, + { + internalType: "uint256", + name: "minimumValue", + type: "uint256", + }, + ], + name: "setAssetAddressInfo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint64", + name: "dest_chain_id", + type: "uint64", + }, + { + internalType: "bool", + name: "is_evm", + type: "bool", + }, + { + internalType: "bool", + name: "is_substrate", + type: "bool", + }, + { + internalType: "bytes1", + name: "raw_chain_index", + type: "bytes1", + }, + ], + name: "setDestChainInfo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "enum MoonbeamSlpx.Operation", + name: "_operation", + type: "uint8", + }, + { + internalType: "uint64", + name: "_transactRequiredWeightAtMost", + type: "uint64", + }, + { + internalType: "uint64", + name: "_overallWeight", + type: "uint64", + }, + { + internalType: "uint256", + name: "_feeAmount", + type: "uint256", + }, + ], + name: "setOperationToFeeInfo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_logic", + type: "address", + }, + { + internalType: "address", + name: "admin_", + type: "address", + }, + { + internalType: "bytes", + name: "_data", + type: "bytes", + }, + ], + stateMutability: "payable", + type: "constructor", + }, +]; + +export const mockErc20Abi = [ + { + inputs: [ + { + internalType: "string", + name: "name", + type: "string", + }, + { + internalType: "string", + name: "symbol", + type: "string", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "ERC20InvalidSpender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export const yieldFarmingAbi = [ + { + inputs: [ + { + internalType: "address", + name: "_lpToken", + type: "address", + }, + { + internalType: "address", + name: "_rewardToken", + type: "address", + }, + { + internalType: "uint256", + name: "_rewardRate", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + inputs: [], + name: "ReentrancyGuardReentrantCall", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "EmergencyWithdrawn", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "RewardsClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Staked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Withdrawn", + type: "event", + }, + { + inputs: [], + name: "BOOST_THRESHOLD_1", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BOOST_THRESHOLD_2", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BOOST_THRESHOLD_3", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_user", + type: "address", + }, + ], + name: "calculateBoostMultiplier", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "claimRewards", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_user", + type: "address", + }, + ], + name: "earned", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "emergencyWithdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lastUpdateTime", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lpToken", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_user", + type: "address", + }, + ], + name: "pendingRewards", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "rewardPerToken", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardPerTokenStored", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardRate", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardToken", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + ], + name: "stake", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "totalStaked", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_newRate", + type: "uint256", + }, + ], + name: "updateRewardRate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "userInfo", + outputs: [ + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + internalType: "uint256", + name: "startTime", + type: "uint256", + }, + { + internalType: "uint256", + name: "rewardDebt", + type: "uint256", + }, + { + internalType: "uint256", + name: "pendingRewards", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + ], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export const vestingAbi = [ + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cliff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "createVestingSchedule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + } + ], + "name": "getVestingSchedule", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "totalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cliff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "releasedAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "revoked", + "type": "bool" + } + ], + "internalType": "struct TokenVesting.VestingSchedule", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + } + ], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + } + ], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const; + +export const VESTING_CONTRACT_ADDRESS = "0x93bfafffe5911442f7bec0d9c186479dccff5443"; \ No newline at end of file diff --git a/challenge-3-frontend/lib/config.ts b/challenge-3-frontend/lib/config.ts new file mode 100644 index 0000000..d9f05d7 --- /dev/null +++ b/challenge-3-frontend/lib/config.ts @@ -0,0 +1,7 @@ +export const LP_ADDRESS = + "0x507704Ae184bf2fe699525f33aE3A577d7486437"; +export const REWARD_ADDRESS = + "0x439Bced6319443965D4479Ac97101fD8d8453596"; +export const YIELD_FARM_ADDRESS = + "0xc886861b6d5585C7590B1B6Ce4140a063d360627"; +export const VESTING_ADDRESS = "0x93bfafffe5911442f7bec0d9c186479dccff5443"; From 513d249709ed960f64aed5ae5777225fa44075bc Mon Sep 17 00:00:00 2001 From: kaksv Date: Tue, 6 May 2025 21:40:43 +0300 Subject: [PATCH 3/3] Kakooza Vianey | Register for OpenGuild x Encode Club Challenges --- challenge-1-vesting/README.md | 2 +- challenge-2-yield-farm/README.md | 2 +- challenge-3-frontend/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/challenge-1-vesting/README.md b/challenge-1-vesting/README.md index e8554d5..4b7e4d4 100644 --- a/challenge-1-vesting/README.md +++ b/challenge-1-vesting/README.md @@ -34,7 +34,7 @@ source ~/.bashrc # for bash source ~/.zshrc # for zsh ``` -### 2. Install Node.js and npm using Volta +### 2. Install Node.js and npm using Volta. ```bash # Install Node.js LTS version diff --git a/challenge-2-yield-farm/README.md b/challenge-2-yield-farm/README.md index 14515fc..d5bd73e 100644 --- a/challenge-2-yield-farm/README.md +++ b/challenge-2-yield-farm/README.md @@ -25,7 +25,7 @@ source ~/.bashrc # for bash source ~/.zshrc # for zsh ``` -### 2. Install Node.js and npm using Volta +### 2. Install Node.js and npm using Volta. ```bash # Install Node.js LTS version diff --git a/challenge-3-frontend/README.md b/challenge-3-frontend/README.md index 7b8d41f..0ab5c8f 100644 --- a/challenge-3-frontend/README.md +++ b/challenge-3-frontend/README.md @@ -1,4 +1,4 @@ -# DOT UI Kit +# DOT UI Kit. An open-source, up-to-date, opinionated UI scaffolding kit for the Polkadot ecosystem (starting with Asset Hub). The technical stack is: