const troveManageABI = [ { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_activePoolAddress", type: "address", }, ], name: "ActivePoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_baseRate", type: "uint256", }, ], name: "BaseRateUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_newBorrowerOperationsAddress", type: "address", }, ], name: "BorrowerOperationsAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_collSurplusPoolAddress", type: "address", }, ], name: "CollSurplusPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_defaultPoolAddress", type: "address", }, ], name: "DefaultPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_gasPoolAddress", type: "address", }, ], name: "GasPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_lqtyStakingAddress", type: "address", }, ], name: "LQTYStakingAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_lqtyTokenAddress", type: "address", }, ], name: "LQTYTokenAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_L_ETH", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_L_LUSDDebt", type: "uint256", }, ], name: "LTermsUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_newLUSDTokenAddress", type: "address", }, ], name: "LUSDTokenAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_lastFeeOpTime", type: "uint256", }, ], name: "LastFeeOpTimeUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_liquidatedDebt", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_liquidatedColl", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_collGasCompensation", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_LUSDGasCompensation", type: "uint256", }, ], name: "Liquidation", 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: "_newPriceFeedAddress", type: "address", }, ], name: "PriceFeedAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_attemptedLUSDAmount", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_actualLUSDAmount", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_ETHSent", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_ETHFee", type: "uint256", }, ], name: "Redemption", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_sortedTrovesAddress", type: "address", }, ], name: "SortedTrovesAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_stabilityPoolAddress", type: "address", }, ], name: "StabilityPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_totalStakesSnapshot", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_totalCollateralSnapshot", type: "uint256", }, ], name: "SystemSnapshotsUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_newTotalStakes", type: "uint256", }, ], name: "TotalStakesUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "_newIndex", type: "uint256", }, ], name: "TroveIndexUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "_debt", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_coll", type: "uint256", }, { indexed: false, internalType: "enum TroveManager.TroveManagerOperation", name: "_operation", type: "uint8", }, ], name: "TroveLiquidated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_L_ETH", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_L_LUSDDebt", type: "uint256", }, ], name: "TroveSnapshotsUpdated", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "_debt", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_coll", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_stake", type: "uint256", }, { indexed: false, internalType: "enum TroveManager.TroveManagerOperation", name: "_operation", type: "uint8", }, ], name: "TroveUpdated", type: "event", }, { inputs: [], name: "BETA", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "BOOTSTRAP_PERIOD", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "BORROWING_FEE_FLOOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "CCR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "DECIMAL_PRECISION", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "LUSD_GAS_COMPENSATION", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "L_ETH", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "L_LUSDDebt", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MAX_BORROWING_FEE", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MCR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MINUTE_DECAY_FACTOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MIN_NET_DEBT", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "NAME", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function", }, { inputs: [], name: "PERCENT_DIVISOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "REDEMPTION_FEE_FLOOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "SECONDS_IN_ONE_MINUTE", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "", type: "uint256" }], name: "TroveOwners", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "", type: "address" }], name: "Troves", outputs: [ { internalType: "uint256", name: "debt", type: "uint256" }, { internalType: "uint256", name: "coll", type: "uint256" }, { internalType: "uint256", name: "stake", type: "uint256" }, { internalType: "enum TroveManager.Status", name: "status", type: "uint8", }, { internalType: "uint128", name: "arrayIndex", type: "uint128" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "_100pct", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "activePool", outputs: [ { internalType: "contract IActivePool", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "addTroveOwnerToArray", outputs: [{ internalType: "uint256", name: "index", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "applyPendingRewards", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "baseRate", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address[]", name: "_troveArray", type: "address[]" }, ], name: "batchLiquidateTroves", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "borrowerOperationsAddress", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_price", type: "uint256" }], name: "checkRecoveryMode", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "closeTrove", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "decayBaseRateFromBorrowing", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_collDecrease", type: "uint256" }, ], name: "decreaseTroveColl", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_debtDecrease", type: "uint256" }, ], name: "decreaseTroveDebt", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "defaultPool", outputs: [ { internalType: "contract IDefaultPool", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_LUSDDebt", type: "uint256" }], name: "getBorrowingFee", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_LUSDDebt", type: "uint256" }], name: "getBorrowingFeeWithDecay", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "getBorrowingRate", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "getBorrowingRateWithDecay", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_price", type: "uint256" }, ], name: "getCurrentICR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getEntireDebtAndColl", outputs: [ { internalType: "uint256", name: "debt", type: "uint256" }, { internalType: "uint256", name: "coll", type: "uint256" }, { internalType: "uint256", name: "pendingLUSDDebtReward", type: "uint256", }, { internalType: "uint256", name: "pendingETHReward", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "getEntireSystemColl", outputs: [ { internalType: "uint256", name: "entireSystemColl", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "getEntireSystemDebt", outputs: [ { internalType: "uint256", name: "entireSystemDebt", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getNominalICR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getPendingETHReward", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getPendingLUSDDebtReward", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_ETHDrawn", type: "uint256" }], name: "getRedemptionFeeWithDecay", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "getRedemptionRate", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "getRedemptionRateWithDecay", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_price", type: "uint256" }], name: "getTCR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getTroveColl", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getTroveDebt", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_index", type: "uint256" }], name: "getTroveFromTroveOwnersArray", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "getTroveOwnersCount", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getTroveStake", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "getTroveStatus", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "hasPendingRewards", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_collIncrease", type: "uint256" }, ], name: "increaseTroveColl", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_debtIncrease", type: "uint256" }, ], name: "increaseTroveDebt", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "isOwner", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function", }, { inputs: [], name: "lastETHError_Redistribution", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "lastFeeOperationTime", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "lastLUSDDebtError_Redistribution", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "liquidate", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "uint256", name: "_n", type: "uint256" }], name: "liquidateTroves", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "lqtyStaking", outputs: [ { internalType: "contract ILQTYStaking", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "lqtyToken", outputs: [ { internalType: "contract ILQTYToken", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "lusdToken", outputs: [ { internalType: "contract ILUSDToken", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "owner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "priceFeed", outputs: [ { internalType: "contract IPriceFeed", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "uint256", name: "_LUSDamount", type: "uint256" }, { internalType: "address", name: "_firstRedemptionHint", type: "address", }, { internalType: "address", name: "_upperPartialRedemptionHint", type: "address", }, { internalType: "address", name: "_lowerPartialRedemptionHint", type: "address", }, { internalType: "uint256", name: "_partialRedemptionHintNICR", type: "uint256", }, { internalType: "uint256", name: "_maxIterations", type: "uint256" }, { internalType: "uint256", name: "_maxFeePercentage", type: "uint256" }, ], name: "redeemCollateral", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "removeStake", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "", type: "address" }], name: "rewardSnapshots", outputs: [ { internalType: "uint256", name: "ETH", type: "uint256" }, { internalType: "uint256", name: "LUSDDebt", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "_borrowerOperationsAddress", type: "address", }, { internalType: "address", name: "_activePoolAddress", type: "address" }, { internalType: "address", name: "_defaultPoolAddress", type: "address" }, { internalType: "address", name: "_stabilityPoolAddress", type: "address", }, { internalType: "address", name: "_gasPoolAddress", type: "address" }, { internalType: "address", name: "_collSurplusPoolAddress", type: "address", }, { internalType: "address", name: "_priceFeedAddress", type: "address" }, { internalType: "address", name: "_lusdTokenAddress", type: "address" }, { internalType: "address", name: "_sortedTrovesAddress", type: "address", }, { internalType: "address", name: "_lqtyTokenAddress", type: "address" }, { internalType: "address", name: "_lqtyStakingAddress", type: "address" }, ], name: "setAddresses", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "uint256", name: "_num", type: "uint256" }, ], name: "setTroveStatus", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "sortedTroves", outputs: [ { internalType: "contract ISortedTroves", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "stabilityPool", outputs: [ { internalType: "contract IStabilityPool", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "totalCollateralSnapshot", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "totalStakes", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "totalStakesSnapshot", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "updateStakeAndTotalStakes", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "_borrower", type: "address" }], name: "updateTroveRewardSnapshots", outputs: [], stateMutability: "nonpayable", type: "function", }, ]; const priceFeedABI = [ { anonymous: false, inputs: [ { indexed: false, internalType: "uint256", name: "_lastGoodPrice", type: "uint256", }, ], name: "LastGoodPriceUpdated", type: "event", }, { inputs: [], name: "fetchPrice", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "getPrice", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "price", type: "uint256" }], name: "setPrice", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, ]; const borrowerOperationsABI = [ { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_activePoolAddress", type: "address", }, ], name: "ActivePoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_collSurplusPoolAddress", type: "address", }, ], name: "CollSurplusPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_defaultPoolAddress", type: "address", }, ], name: "DefaultPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_gasPoolAddress", type: "address", }, ], name: "GasPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_lqtyStakingAddress", type: "address", }, ], name: "LQTYStakingAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "_LUSDFee", type: "uint256", }, ], name: "LUSDBorrowingFeePaid", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_lusdTokenAddress", type: "address", }, ], name: "LUSDTokenAddressChanged", 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: "_newPriceFeedAddress", type: "address", }, ], name: "PriceFeedAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_sortedTrovesAddress", type: "address", }, ], name: "SortedTrovesAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_stabilityPoolAddress", type: "address", }, ], name: "StabilityPoolAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "arrayIndex", type: "uint256", }, ], name: "TroveCreated", type: "event", }, { anonymous: false, inputs: [ { indexed: false, internalType: "address", name: "_newTroveManagerAddress", type: "address", }, ], name: "TroveManagerAddressChanged", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "_borrower", type: "address", }, { indexed: false, internalType: "uint256", name: "_debt", type: "uint256", }, { indexed: false, internalType: "uint256", name: "_coll", type: "uint256", }, { indexed: false, internalType: "uint256", name: "stake", type: "uint256", }, { indexed: false, internalType: "enum BorrowerOperations.BorrowerOperation", name: "operation", type: "uint8", }, ], name: "TroveUpdated", type: "event", }, { inputs: [], name: "BORROWING_FEE_FLOOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "CCR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "DECIMAL_PRECISION", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "LUSD_GAS_COMPENSATION", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MCR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "MIN_NET_DEBT", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "NAME", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function", }, { inputs: [], name: "PERCENT_DIVISOR", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "_100pct", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "activePool", outputs: [ { internalType: "contract IActivePool", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "addColl", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "_maxFeePercentage", type: "uint256" }, { internalType: "uint256", name: "_collWithdrawal", type: "uint256" }, { internalType: "uint256", name: "_LUSDChange", type: "uint256" }, { internalType: "bool", name: "_isDebtIncrease", type: "bool" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "adjustTrove", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [], name: "claimCollateral", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "closeTrove", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "defaultPool", outputs: [ { internalType: "contract IDefaultPool", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "uint256", name: "_debt", type: "uint256" }], name: "getCompositeDebt", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, { inputs: [], name: "getEntireSystemColl", outputs: [ { internalType: "uint256", name: "entireSystemColl", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "getEntireSystemDebt", outputs: [ { internalType: "uint256", name: "entireSystemDebt", type: "uint256" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "isOwner", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function", }, { inputs: [], name: "lqtyStaking", outputs: [ { internalType: "contract ILQTYStaking", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "lqtyStakingAddress", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "lusdToken", outputs: [ { internalType: "contract ILUSDToken", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "_borrower", type: "address" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "moveETHGainToTrove", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "_maxFeePercentage", type: "uint256" }, { internalType: "uint256", name: "_LUSDAmount", type: "uint256" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "openTrove", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [], name: "owner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "priceFeed", outputs: [ { internalType: "contract IPriceFeed", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "uint256", name: "_LUSDAmount", type: "uint256" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "repayLUSD", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "_troveManagerAddress", type: "address", }, { internalType: "address", name: "_activePoolAddress", type: "address" }, { internalType: "address", name: "_defaultPoolAddress", type: "address" }, { internalType: "address", name: "_stabilityPoolAddress", type: "address", }, { internalType: "address", name: "_gasPoolAddress", type: "address" }, { internalType: "address", name: "_collSurplusPoolAddress", type: "address", }, { internalType: "address", name: "_priceFeedAddress", type: "address" }, { internalType: "address", name: "_sortedTrovesAddress", type: "address", }, { internalType: "address", name: "_lusdTokenAddress", type: "address" }, { internalType: "address", name: "_lqtyStakingAddress", type: "address" }, ], name: "setAddresses", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "sortedTroves", outputs: [ { internalType: "contract ISortedTroves", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "troveManager", outputs: [ { internalType: "contract ITroveManager", name: "", type: "address" }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "uint256", name: "_collWithdrawal", type: "uint256" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "withdrawColl", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "uint256", name: "_maxFeePercentage", type: "uint256" }, { internalType: "uint256", name: "_LUSDAmount", type: "uint256" }, { internalType: "address", name: "_upperHint", type: "address" }, { internalType: "address", name: "_lowerHint", type: "address" }, ], name: "withdrawLUSD", outputs: [], stateMutability: "nonpayable", type: "function", }, ]; const ManageWrapper = styled.div` width : 100%; display: flex; flex-direction: column; align-items: center; .option-wrapper { width: 100%; height: 2rem; } .option { height: 100%; border-radius: 10px; padding: 0 1rem 0 1rem; } .input-wrapper { display: flex; width: 100%; border: rgb(220, 220, 220) 1px solid; margin: 0.5rem; border-radius: 10px; overflow: hidden; } .token-wrapper { display: flex; } .token { padding: 0 0.5rem 0 0.5rem; } .error-message { } .confirm-wrapper{ width: 100%; display: flex; justify-content: center; } .confirm { border: none; border-radius: 1000px; width: 50%; height: 2.3rem; transition: 0.5s all; font-size: 1.3rem; font-weight: 600; display: flex; align-items: center; justify-content: center; &.ok { background-color: #755ddf; color: white; } &.not-ok{ background-color: #8e9aaf; color: white; } } .info-wrapper { margin: 2rem 0 2rem 0 ; width: 100%; div{ height: 1.75rem; display: flex; align-items: center; } span{ } } .info{ width: 100%; display: flex; justify-content: space-between; color: #8e9aaf; } .after{ &.ok{ color: green; } &.not-ok{ color: red; } } .unit{ margin-left: 0.5rem; } button { border: none; transition: 0.3s all; &.active { background-color: #755ddf; color: white; } &.disabled { background-color: rgb(240, 240, 240); color: gray; } } input { border: none; } input:focus { outline: none; } input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } `; // Trove 없으면 Trove 만들어. 에러메세지 // ICR이 MCR 이상인지? 이상이 아니라면 에러메세지 State.init({ option: "withdraw", token: "ETH", address: null, check: false }); const troveManageAddress = "0x0ECDF34731eE8Dd46caa99a1AAE173beD1B32c67"; const priceFeedAddress = "0x07dD4Ce17De84bA13Fc154A7FdB46fC362a41E2C"; const borrowerOperationsAddress = "0xD69fC8928D4F3229341cb431263F1EBd87B1ade8"; // const troveManageABI = fetch( // "https://api-sepolia.etherscan.io/api?module=contract&action=getabi&address=0x8a4Dc4AA9fB4542Be5158C5D35E1bcC83FEE2136" // ); // const priceFeedABI = fetch( // "https://api-sepolia.etherscan.io/api?module=contract&action=getabi&address=0x330804fA8DA14ec5Fe3de325ED41Aa41525b04a3" // ); // const troveManageInterface = new ethers.utils.Interface( // troveManageABI.body.result // ); // const priceFeedInterface = new ethers.utils.Interface(priceFeedABI.body.result); const troveManageInterface = new ethers.utils.Interface(troveManageABI); const priceFeedInterface = new ethers.utils.Interface(priceFeedABI); const EPSILON = 2.2e-16; if (Ethers.provider()) { const signer = Ethers.provider().getSigner(); signer.getAddress().then((address) => { State.update({ address }); }); // Price 조회 const encodedForPrice = priceFeedInterface.encodeFunctionData("getPrice"); Ethers.provider() .call({ to: priceFeedAddress, data: encodedForPrice, }) .then((raw) => { const receiverBalanceHex = priceFeedInterface.decodeFunctionResult( "getPrice", raw ); const result = receiverBalanceHex[0].div("1000000000000000000"); State.update({ currentPrice: result.toString() }); }); // ICR 조회 const encodedForICR = troveManageInterface.encodeFunctionData( "getCurrentICR", [state.address, "2000000000000000000000"] ); Ethers.provider() .call({ to: troveManageAddress, data: encodedForICR, }) .then((raw) => { const receiverBalanceHex = troveManageInterface.decodeFunctionResult( "getCurrentICR", raw ); const result = receiverBalanceHex[0].div("1000000000000000000"); State.update({ currentICR: result.toString() }); }); // Collateral 조회 const encodedForColl = troveManageInterface.encodeFunctionData( "getTroveColl", [state.address] ); Ethers.provider() .call({ to: troveManageAddress, data: encodedForColl, }) .then((raw) => { const receiverBalanceHex = troveManageInterface.decodeFunctionResult( "getTroveColl", raw ); State.update({ currentColl: ethers.utils .formatEther(receiverBalanceHex[0].toString()) .toString(), }); }); // debt 조회 const encodedForDebt = troveManageInterface.encodeFunctionData( "getTroveDebt", [state.address] ); Ethers.provider() .call({ to: troveManageAddress, data: encodedForDebt, }) .then((raw) => { const receiverBalanceHex = troveManageInterface.decodeFunctionResult( "getTroveDebt", raw ); const result = receiverBalanceHex[0].div("1000000000000000000"); State.update({ currentDebt: result.toString() }); }); } const checkFunc = () => { // Ratio 1.1 이상일 것 // Debt 가 2000 이상일 것 if (!state.value) { State.update({ check: false }); return; } if (state.updatedICR < 1.1) { State.update({ check: false }); return; } if (state.updatedDebt < 2000) { State.update({ check: false }); return; } State.update({ check: true }); }; const changeHandler = (e) => { const value = e.target.value; State.update({ value: e.target.value }); // deposit-ETH if (state.option === "deposit" && state.token === "ETH") { State.update({ updatedColl: Number(state.currentColl) + Number(value), updatedICR: e.target.value === "" ? null : Math.round( (((Number(state.currentColl) + Number(value)) / Number(state.currentDebt)) * Number(state.currentPrice) + EPSILON) * 100 ) / 100, }); } // withdraw-ETH else if (state.option === "withdraw" && state.token === "ETH") { State.update({ updatedColl: Number(state.currentColl) - Number(value), updatedICR: e.target.value === "" ? null : Math.round( (((Number(state.currentColl) - Number(value)) / Number(state.currentDebt)) * Number(state.currentPrice) + EPSILON) * 100 ) / 100, }); } // deposit-LUSD else if (state.option === "deposit" && state.token === "LUSD") { State.update({ updatedDebt: Number(state.currentDebt) - Number(value), updatedICR: e.target.value === "" ? null : Math.round( ((Number(state.currentColl) / (Number(state.currentDebt) - Number(value))) * Number(state.currentPrice) + EPSILON) * 100 ) / 100, }); } // withdraw-LUSD else if (state.option === "withdraw" && state.token === "LUSD") { State.update({ updatedDebt: Number(state.currentDebt) + Number(value), updatedICR: e.target.value === "" ? null : Math.round( ((Number(state.currentColl) / (Number(state.currentDebt) + Number(value))) * Number(state.currentPrice) + EPSILON) * 100 ) / 100, }); } checkFunc(); }; const optionHandler = (option) => { State.update({ option: option }); changeHandler({ target: { value: Number(state.value) } }); }; const tokenHandler = (token) => { State.update({ token: token }); changeHandler({ target: { value: Number(state.value) } }); }; const confirmHandler = () => { if (!state.check) { return; } const borrowerOperationsContract = new ethers.Contract( borrowerOperationsAddress, borrowerOperationsABI, Ethers.provider().getSigner() ); const amount = ethers.utils.parseUnits(state.value, "ether").toString(); if (state.option === "deposit" && state.token === "ETH") { borrowerOperationsContract .addColl(state.address, state.address, { value: amount }) .then((transactionHash) => { console.log(transactionHash.hash); }); } else if (state.option === "withdraw" && state.token === "ETH") { borrowerOperationsContract .withdrawColl(amount.toString(), state.address, state.address) .then((transactionHash) => { console.log(transactionHash.hash); }); } else if (state.option === "deposit" && state.token === "LUSD") { borrowerOperationsContract .repayLUSD(amount.toString(), state.address, state.address) .then((transactionHash) => { console.log(transactionHash.hash); }); } else if (state.option === "withdraw" && state.token === "LUSD") { borrowerOperationsContract .withdrawLUSD( "5000000000000000", amount.toString(), state.address, state.address ) .then((transactionHash) => { console.log(transactionHash.hash); }); } }; return ( <ManageWrapper> <Web3Connect /> <div className="option-wrapper"> <button className={`option ${ state.option === "deposit" ? "active" : "disabled" }`} onClick={() => { optionHandler("deposit"); }} > deposit </button> <button className={`option ${ state.option === "withdraw" ? "active" : "disabled" }`} onClick={() => { optionHandler("withdraw"); }} > withdraw </button> </div> <div className="input-wrapper"> <input type="number" placeholder={state.token === "ETH" ? "0.0000 ETH" : "0.0000 LUSD"} onChange={changeHandler} value={state.value} ></input> <div className={`token-wrapper`}> <button onClick={() => { tokenHandler("ETH"); }} className={`token ${state.token === "ETH" ? "active" : "disabled"}`} > ETH </button> <button onClick={() => { tokenHandler("LUSD"); }} className={`token ${state.token === "LUSD" ? "active" : "disabled"}`} > LUSD </button> </div> </div> <div className="info-wrapper"> <div className="info"> <div>Your Collateral Ratio</div> <div> {!isNaN( (((Number(state.currentColl) / Number(state.currentDebt)) * Number(state.currentPrice) + EPSILON) * 100) / 100 ) ? Math.round( ((Number(state.currentColl) / Number(state.currentDebt)) * Number(state.currentPrice) + EPSILON) * 100 ) / 100 : "-"} <span className={`after ${state.updatedICR >= 1.1 ? "ok" : "not-ok"}`} > {state.updatedICR && Number(state.updatedICR) !== Number( Math.round( ((Number(state.currentColl) / Number(state.currentDebt)) * Number(state.currentPrice) + EPSILON) * 100 ) / 100 ) ? state.updatedICR > 0 ? `=> ${state.updatedICR}` : "" : ""} </span> </div> </div> <div className="info"> <div>Your Collateral</div> <div> {state.currentColl}{" "} <span className={`after`}> {state.updatedColl && Number(state.updatedColl) !== Number(state.currentColl) ? `=> ${state.updatedColl}` : ""} </span>{" "} <span className="unit">ETH</span> </div> </div> <div className="info"> <div>Your Debt</div> <div> {state.currentDebt}{" "} <span className={`after ${state.updatedDebt >= 2000 ? "ok" : "not-ok"}`} > {state.updatedDebt && state.updatedDebt.toString() !== state.currentDebt.toString() ? state.updatedDebt > 0 ? `=> ${state.updatedDebt}` : `=> 0` : ""} </span>{" "} <span className="unit">LUSD</span> </div> </div> <div className="info"> <div>Ethereum Price</div> <div> {state.currentPrice} <span className="unit">$</span> </div> </div> </div> <div className="confirm-wrapper" onClick={confirmHandler}> <button className={`confirm ${state.check ? "ok" : "not-ok"}`}> {state.check ? `Confirm ${state.option}` : !state.value ? "Enter input value" : "Check stats"} </button> </div> </ManageWrapper> );