diff --git a/README.md b/README.md
index ee62858..7472a85 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 |
+| 🦄 | Emmanuel Bagoole | ManuelPrhyme | Solidity Smart Contracts Instructor/Auditor |
```
- Step 5: `Commit` your code and push to the forked Github repository
diff --git a/challenge-1-vesting/README.md b/challenge-1-vesting/README.md
index 9cc7a2c..7296e27 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 |
+| 🎅 | Manuel | [ManuelPrhyme](https://github.com/ManuelPrhyme) | Smart-Contracts Engineer |
## 💻 Local development environment setup
diff --git a/challenge-1-vesting/contracts/TokenVesting.sol b/challenge-1-vesting/contracts/TokenVesting.sol
index 43d4c3a..03bfde0 100644
--- a/challenge-1-vesting/contracts/TokenVesting.sol
+++ b/challenge-1-vesting/contracts/TokenVesting.sol
@@ -1,148 +1,196 @@
-// 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;
+pragma solidity ^0.8.25;
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";
+// Token Address
+// Vesting ["VST"] -> 0xD2f45381d4aAd3B29C26E9FD86dAb8B98E2FE238
+// Staked ["SKT"] -> 0xcac8028b3361da8729a6ce521503ce88a50a4806
+// Vested ["VES"] -> 0x14574a3d70554722a14c0cbc50ab0e7834ac66a5
+
contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard {
- struct VestingSchedule {
- // TODO: Define the vesting schedule struct
- }
+ address Owner;
+
// Token being vested
- // TODO: Add state variables
+ IERC20 public Vestings;
+ IERC20 internal Staked;
+ IERC20 internal Vested;
+ //Vesting schedule for each beneficiary
+ struct VestingSchedule {
+ uint256 totalAmount;
+ uint256 startTime;
+ uint256 cliffDuration;
+ uint256 vestingDuration;
+ uint256 amountClaimed;
+ string Token;
+ bool revokedStatus;
+ }
- // Mapping from beneficiary to vesting schedule
- // TODO: Add state variables
+ //Mapping from beneficiary to vesting schedule created
+ mapping(address=>VestingSchedule) public beneficiaryScheduled;
- // Whitelist of beneficiaries
- // TODO: Add state variables
+ //Whitelist of beneficiaries
+ mapping(address=>bool) public beneficiaryWhitelist;
// Events
- event VestingScheduleCreated(address indexed beneficiary, uint256 amount);
+ event VestingScheduleCreated(address indexed beneficiary, string token, uint256 amount);
event TokensClaimed(address indexed beneficiary, uint256 amount);
event VestingRevoked(address indexed beneficiary);
- event BeneficiaryWhitelisted(address indexed beneficiary);
- event BeneficiaryRemovedFromWhitelist(address indexed beneficiary);
+ event BeneficiaryWhitelisted(address indexed beneficiary);
+ event BeneficiaryRemovedFromWhitelist(address indexed beneficiary);
- constructor(address tokenAddress) {
- // TODO: Initialize the contract
+ //constructor functions assigns the actual token addresses to the instances created
+ constructor(address _vst, address _stk, address _ves){
+ Vestings = IERC20(_vst);
+ Staked = IERC20(_stk);
+ Vested = IERC20(_ves);
+ Owner = msg.sender;
}
// Modifier to check if beneficiary is whitelisted
modifier onlyWhitelisted(address beneficiary) {
- require(whitelist[beneficiary], "Beneficiary not whitelisted");
+ require(beneficiaryWhitelist[beneficiary], "Beneficiary not whitelisted");
_;
}
function addToWhitelist(address beneficiary) external onlyOwner {
require(beneficiary != address(0), "Invalid address");
- whitelist[beneficiary] = true;
+ beneficiaryWhitelist[beneficiary] = true;
emit BeneficiaryWhitelisted(beneficiary);
}
function removeFromWhitelist(address beneficiary) external onlyOwner {
- whitelist[beneficiary] = false;
+ beneficiaryWhitelist[beneficiary] = false;
emit BeneficiaryRemovedFromWhitelist(beneficiary);
}
+
function createVestingSchedule(
address beneficiary,
uint256 amount,
uint256 cliffDuration,
uint256 vestingDuration,
- uint256 startTime
+ uint256 startTime,
+ string calldata tokenChoice
) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused {
- // TODO: Implement vesting schedule creation
+ //Validation
+ require(amount > 0,'Stake amount greater than 0');
+ require( beneficiary != address(0), 'Enter correct address');
+ require( vestingDuration > cliffDuration, "Enter a valid Vesting duration [Vesting duration must be greater than Cliff duration]");
+ require(vestingDuration > 0,"Vesting duration must be greater that 0");
+
+ //Effects
+ if(startTime == 0 || startTime <= block.timestamp){
+ startTime = block.timestamp;
+ }
+
+ //Interactions
+ //For mutiple token transfer I used an implict references for each token => ['USDT','USDC','DAI']. They could be picked fron a list on the
+ // interface and then a transaction is senn to this function with that string in calldata, to enable with the conditional logic of calling
+ // the trasferFrom method from the correct ERC20 contract
+ if(bytes32(bytes(tokenChoice)) == bytes32('VST')) {
+ Vestings.transferFrom(msg.sender, address(this),amount);
+ }else if(bytes32(bytes(tokenChoice)) == bytes32('STK')){
+ Staked.transferFrom(msg.sender, address(this), amount);
+ } else if(bytes32(bytes(tokenChoice)) == bytes32('VES')) {
+ Vested.transferFrom(msg.sender, address(this),amount);
+ } else {
+ revert('Please choose one of these ["VST","STK","VES"]');
+ }
+
+ //Note: This is an effect (simply a state mutability statemet) but it is necessary that it comes after an interaction of the contract with external
+ // signers, because its records determine how much tokens to a particular beneficiary is released later on. Even though it might jeopardise the
+ // reentracy guard of the contract coming after transfer, the risk of registering a Schedule and not sending actual tokens is just as high. So just incase a
+ // wrong token's transfer is attempted or somehow the transfer fails, the contract shouldn't create a Vesting Schedule, instead it should revert without the line below being executed.
+
+ beneficiaryScheduled[beneficiary] = VestingSchedule(amount,startTime,cliffDuration,vestingDuration,0,tokenChoice,false);
+
+ emit VestingScheduleCreated(beneficiary, tokenChoice, amount);
}
- function calculateVestedAmount(
- address beneficiary
- ) public view returns (uint256) {
- // TODO: Implement vested amount calculation
+ function calculateVestedAmount() public view returns (uint256) {
+ require(beneficiaryWhitelist[msg.sender],"Please connect with the vesting address");
+ require(!beneficiaryScheduled[msg.sender].revokedStatus,"Please initiate a vesting schedule");
+
+ address beneficiary = msg.sender;
+
+ if(block.timestamp <= beneficiaryScheduled[beneficiary].startTime + beneficiaryScheduled[beneficiary].cliffDuration){
+ return 0;
+ }
+
+ if(block.timestamp >= beneficiaryScheduled[beneficiary].startTime + beneficiaryScheduled[beneficiary].vestingDuration){
+ return beneficiaryScheduled[beneficiary].totalAmount;
+
+ }
+
+ uint timeCount = block.timestamp - beneficiaryScheduled[beneficiary].cliffDuration;
+
+ return (beneficiaryScheduled[beneficiary].totalAmount * timeCount) / beneficiaryScheduled[beneficiary].vestingDuration;
+
}
function claimVestedTokens() external nonReentrant whenNotPaused {
- // TODO: Implement token claiming
+ require(beneficiaryWhitelist[msg.sender],"Please connect with the vesting address");
+ require(!beneficiaryScheduled[msg.sender].revokedStatus,"Please initiate a vesting schedule");
+ require(beneficiaryScheduled[msg.sender].amountClaimed < beneficiaryScheduled[msg.sender].totalAmount ,"All claimable amount has been withdrawn");
+
+ uint claimableAmount = calculateVestedAmount() - beneficiaryScheduled[msg.sender].amountClaimed;
+ beneficiaryScheduled[msg.sender].amountClaimed = claimableAmount;
+
+ require(claimableAmount > 0,"All claimble tokens have been claimed");
+
+ string memory VestedToken = beneficiaryScheduled[msg.sender].Token;
+
+ if(bytes32(bytes(VestedToken)) == bytes32('VST')){
+ require(Vestings.transfer(msg.sender,claimableAmount),'Transaction failed');
+
+ } else if(bytes32(bytes(VestedToken)) == bytes32('STK')){
+ require(Staked.transfer(msg.sender,claimableAmount),'Transaction failed');
+
+ } else {
+ require(Vested.transfer(msg.sender,claimableAmount),'Transaction failed');
+
+ }
+
+ emit TokensClaimed(msg.sender, claimableAmount);
}
- function revokeVesting(address beneficiary) external onlyOwner {
- // TODO: Implement vesting revocation
+ function revokeVesting() external onlyOwner {
+ require(beneficiaryWhitelist[msg.sender],"Please connect with the vesting address");
+ require(!beneficiaryScheduled[msg.sender].revokedStatus,"No vesting schedule found");
+
+ uint Unvested = beneficiaryScheduled[msg.sender].totalAmount - calculateVestedAmount();
+ string memory VestedToken = beneficiaryScheduled[msg.sender].Token;
+
+ if (Unvested > 0){
+ if(bytes32(bytes(VestedToken)) == bytes32('VST')){
+ require(Vestings.transfer(msg.sender,Unvested),'Transaction failed');
+
+ } else if(bytes32(bytes(VestedToken)) == bytes32('STK')){
+ require(Staked.transfer(msg.sender,Unvested),'Transaction failed');
+
+ } else {
+ require(Vested.transfer(msg.sender,Unvested),'Transaction failed'); }
+ }
+ beneficiaryScheduled[msg.sender].revokedStatus = true;
+
+ emit VestingRevoked(msg.sender);
}
- function pause() external onlyOwner {
+ function Pause() external onlyOwner {
_pause();
}
- function unpause() external onlyOwner {
+ 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
diff --git a/challenge-2-yield-farm/contracts/yeild.sol b/challenge-2-yield-farm/contracts/yeild.sol
deleted file mode 100644
index 421496a..0000000
--- a/challenge-2-yield-farm/contracts/yeild.sol
+++ /dev/null
@@ -1,185 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-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
- }
-
- // 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
- }
-
- function updateReward(address _user) internal {
- rewardPerTokenStored = rewardPerToken();
- lastUpdateTime = block.timestamp;
-
- if (_user != address(0)) {
- UserInfo storage user = userInfo[_user];
- user.pendingRewards = earned(_user);
- user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18;
- }
- }
-
- 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
- }
-
- 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
- }
-
- /**
- * @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
- }
-
- /**
- * @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
- }
-
- /**
- * @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
- }
-
- /**
- * @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
- }
-
- /**
- * @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
- }
-
- /**
- * @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
- }
-
- /**
- * @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);
- }
-}
diff --git a/challenge-2-yield-farm/contracts/yield.sol b/challenge-2-yield-farm/contracts/yield.sol
new file mode 100644
index 0000000..4e28d82
--- /dev/null
+++ b/challenge-2-yield-farm/contracts/yield.sol
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.25;
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
+import "@openzeppelin/contracts/access/Ownable.sol";
+
+contract YieldFarm is ReentrancyGuard, Ownable {
+
+ IERC20 public LPToken;
+ IERC20 public rewardToken;
+
+ uint256 public rewardRate;
+ uint256 public lastUpdateTime;
+ uint256 public rewardPerTokenStored;
+ uint256 public totalStaked;
+
+ struct UserInfo {
+ uint256 amount; // Amount of LP tokens staked by user
+ uint256 startTime; // Timestamp when user started staking or last reset
+ uint256 rewardDebt; // Reward debt to track already accounted rewards
+ uint256 pendingRewards; // Rewards accrued but not yet claimed
+ }
+
+ mapping(address => UserInfo) public userInfo;
+
+ 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);
+ event RewardRateUpdated(uint256 oldRate, uint256 newRate);
+
+ // LP Tokens [LP] -> 0x0474b473a1c7bcf9a5706e71e894033157e85248
+ // Reward [RD] -> 0xcd961fde084836941e6f6470d70b5bddfb2739bd
+
+ constructor(
+ address _lpToken,
+ address _rewardToken,
+ uint256 _rewardRate
+ ) {
+ require(_lpToken != address(0), "LP token address zero");
+ require(_rewardToken != address(0), "Reward token address zero");
+ require(_rewardRate > 0, "Reward rate must be > 0");
+
+ LPToken = IERC20(_lpToken);
+ rewardToken = IERC20(_rewardToken);
+ rewardRate = _rewardRate;
+ lastUpdateTime = block.timestamp;
+ }
+
+ function updateReward(address _user) internal {
+ rewardPerTokenStored = rewardPerToken();
+ lastUpdateTime = block.timestamp;
+
+ if (_user != address(0)) {
+ UserInfo storage user = userInfo[_user];
+ user.pendingRewards = earned(_user);
+ user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18;
+ }
+ }
+
+ function rewardPerToken() public view returns (uint256) {
+ if (totalStaked == 0) {
+ return rewardPerTokenStored;
+ }
+ uint256 timeElapsed = block.timestamp - lastUpdateTime;
+ uint256 rewardAccrued = timeElapsed * rewardRate * 1e18 / totalStaked;
+ return rewardPerTokenStored + rewardAccrued;
+}
+
+
+
+
+ function earned(address _user) public view returns (uint256) {
+ UserInfo storage user = userInfo[_user];
+ uint256 currentRewardPerToken = rewardPerToken();
+ uint256 baseReward = (user.amount * (currentRewardPerToken - user.rewardDebt)) / 1e18;
+ uint256 totalReward = user.pendingRewards + baseReward;
+
+ uint256 boostMultiplier = calculateBoostMultiplier(_user);
+ return (totalReward * boostMultiplier) / 100;
+}
+
+
+ function stake(uint256 _amount) external nonReentrant {
+ require(_amount > 0, "Cannot stake zero");
+
+ updateReward(msg.sender);
+
+ UserInfo storage user = userInfo[msg.sender];
+
+ // If first time staking or after emergency withdraw, reset startTime
+ if (user.amount == 0) {
+ user.startTime = block.timestamp;
+ }
+
+ // Transfer LP tokens from user to contract
+ require(LPToken.transferFrom(msg.sender, address(this), _amount), "LP transfer failed");
+
+ user.amount += _amount;
+ totalStaked += _amount;
+
+ // Update reward debt after stake
+ user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18;
+
+ emit Staked(msg.sender, _amount);
+ }
+
+ function withdraw(uint256 _amount) external nonReentrant {
+ UserInfo storage user = userInfo[msg.sender];
+ require(_amount > 0, "Cannot withdraw zero");
+ require(user.amount >= _amount, "Withdraw amount exceeds balance");
+
+ updateReward(msg.sender);
+
+ user.amount -= _amount;
+ totalStaked -= _amount;
+
+ require(LPToken.transfer(msg.sender, _amount), "LP transfer failed");
+
+ if (user.amount == 0) {
+ user.startTime = 0;
+ }
+
+ user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18;
+
+ emit Withdrawn(msg.sender, _amount);
+ }
+
+ function claimRewards() external nonReentrant {
+ updateReward(msg.sender);
+
+ UserInfo storage user = userInfo[msg.sender];
+ uint256 reward = user.pendingRewards;
+ require(reward > 0, "No rewards to claim");
+
+ user.pendingRewards = 0;
+ user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18;
+
+ require(rewardToken.transfer(msg.sender, reward), "Reward transfer failed");
+
+ emit RewardsClaimed(msg.sender, reward);
+ }
+
+ function emergencyWithdraw() external nonReentrant {
+ UserInfo storage user = userInfo[msg.sender];
+ uint256 amount = user.amount;
+ require(amount > 0, "Nothing to withdraw");
+
+ user.amount = 0;
+ user.rewardDebt = 0;
+ user.pendingRewards = 0;
+ user.startTime = 0;
+
+ totalStaked -= amount;
+
+ require(LPToken.transfer(msg.sender, amount), "LP transfer failed");
+
+ emit EmergencyWithdrawn(msg.sender, amount);
+ }
+
+ function calculateBoostMultiplier(address _user) public view returns (uint256) {
+ UserInfo storage user = userInfo[_user];
+ if (user.startTime == 0 || user.amount == 0) {
+ return 100; // No boost if not staking
+ }
+
+ uint256 stakingDuration = block.timestamp - user.startTime;
+
+ if (stakingDuration >= BOOST_THRESHOLD_3) {
+ return 150; // 1.5x boost
+ } else if (stakingDuration >= BOOST_THRESHOLD_2) {
+ return 130; // 1.3x boost
+ } else if (stakingDuration >= BOOST_THRESHOLD_1) {
+ return 110; // 1.1x boost
+ } else {
+ return 100; // No boost
+ }
+ }
+
+ function updateRewardRate(uint256 _newRate) external onlyOwner {
+ require(_newRate > 0, "Reward rate must be > 0");
+ updateReward(address(0)); // Update global rewards before changing rate
+ uint256 oldRate = rewardRate;
+ rewardRate = _newRate;
+ emit RewardRateUpdated(oldRate, _newRate);
+ }
+
+ function pendingRewards(address _user) external view returns (uint256) {
+ return earned(_user);
+ }
+}
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:
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 (
-
-
-
-
Get started by checking out the demos
-
-
- Wallet
-
-
- Send transaction
-
-
- Write contract
-
-
- Mint/Redeem LST Bifrost
-
-
-
-
-
-
- );
+ 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 (
+
+
+ {isConfirming || isPending ? (
+
+ ) : null}
+ Mint 1000 {label}
+
+
+ );
+}
\ 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 (
+
+
+
+
+ {
+ // Desktop would be using dialog
+ isDesktop ? (
+
+
+
+ Transaction status
+
+
+
+
+ Transaction status
+
+
+ Follow the transaction status below.
+
+
+ {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}
+
+ )}
+
+
+
+ Close
+
+
+
+
+ ) : (
+ // Mobile would be using drawer
+
+
+
+ Transaction status
+
+
+
+
+ Transaction status
+
+ Follow the transaction status below.
+
+
+
+ {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}
+
+ )}
+
+
+
+ Close
+
+
+
+
+ )
+ }
+
+ );
+}
\ 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
+
+
+
+
+
+
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 && (
+
= schedule.totalAmount}
+ >
+ {isClaiming ? "Claiming..." : "Claim Vested Tokens"}
+
+ )}
+
+ ) : (
+
+
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)}
+
+
+ Claim reward
+
+ >
+ ) : null}
+
+
+ {
+ // Desktop would be using dialog
+ isDesktop ? (
+
+
+
+ Transaction status
+
+
+
+
+ Transaction status
+
+
+ Follow the transaction status below.
+
+
+ {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}
+
+ )}
+
+
+
+ Close
+
+
+
+
+ ) : (
+ // Mobile would be using drawer
+
+
+
+ Transaction status
+
+
+
+
+ Transaction status
+
+ Follow the transaction status below.
+
+
+
+ {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}
+
+ )}
+
+
+
+ Close
+
+
+
+
+ )
+ }
+
+ );
+}
\ 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";