编译器
0.8.17+commit.8df45f5f
文件 1 的 24:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 24:BaseMath.sol
pragma solidity ^0.8.17;
contract BaseMath {
uint256 constant public DECIMAL_PRECISION = 1e18;
}
文件 3 的 24:CheckContract.sol
pragma solidity ^0.8.17;
contract CheckContract {
function checkContract(address _account) internal view {
require(_account != address(0), "Account cannot be zero address");
uint256 size;
assembly { size := extcodesize(_account) }
require(size > 0, "Account code size cannot be zero");
}
}
文件 4 的 24:IActivePool.sol
pragma solidity ^0.8.17;
import "./IPool.sol";
interface IActivePool is IPool {
event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
event TroveManagerAddressChanged(address _newTroveManagerAddress);
event ActivePoolTHUSDDebtUpdated(uint256 _THUSDDebt);
event ActivePoolCollateralBalanceUpdated(uint256 _collateral);
event CollateralAddressChanged(address _newCollateralAddress);
event CollSurplusPoolAddressChanged(address _newCollSurplusPoolAddress);
function sendCollateral(address _account, uint256 _amount) external;
function updateCollateralBalance(uint256 _amount) external;
function collateralAddress() external view returns(address);
}
文件 5 的 24:IBorrowerOperations.sol
pragma solidity ^0.8.17;
interface IBorrowerOperations {
event TroveManagerAddressChanged(address _newTroveManagerAddress);
event ActivePoolAddressChanged(address _activePoolAddress);
event DefaultPoolAddressChanged(address _defaultPoolAddress);
event StabilityPoolAddressChanged(address _stabilityPoolAddress);
event GasPoolAddressChanged(address _gasPoolAddress);
event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
event PriceFeedAddressChanged(address _newPriceFeedAddress);
event SortedTrovesAddressChanged(address _sortedTrovesAddress);
event THUSDTokenAddressChanged(address _thusdTokenAddress);
event PCVAddressChanged(address _pcvAddress);
event CollateralAddressChanged(address _newCollateralAddress);
event TroveCreated(address indexed _borrower, uint256 arrayIndex);
event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 stake, uint8 operation);
event THUSDBorrowingFeePaid(address indexed _borrower, uint256 _THUSDFee);
function setAddresses(
address _troveManagerAddress,
address _activePoolAddress,
address _defaultPoolAddress,
address _stabilityPoolAddress,
address _gasPoolAddress,
address _collSurplusPoolAddress,
address _priceFeedAddress,
address _sortedTrovesAddress,
address _thusdTokenAddress,
address _pcvAddress,
address _collateralAddress
) external;
function openTrove(uint256 _maxFee, uint256 _THUSDAmount, uint256 _assetAmount, address _upperHint, address _lowerHint) external payable;
function addColl(uint256 _assetAmount, address _upperHint, address _lowerHint) external payable;
function moveCollateralGainToTrove(address _user, uint256 _assetAmount, address _upperHint, address _lowerHint) external payable;
function withdrawColl(uint256 _amount, address _upperHint, address _lowerHint) external;
function withdrawTHUSD(uint256 _maxFee, uint256 _amount, address _upperHint, address _lowerHint) external;
function repayTHUSD(uint256 _amount, address _upperHint, address _lowerHint) external;
function closeTrove() external;
function adjustTrove(uint256 _maxFee, uint256 _collWithdrawal, uint256 _debtChange, bool isDebtIncrease, uint256 _assetAmount, address _upperHint, address _lowerHint) external payable;
function claimCollateral() external;
function getCompositeDebt(uint256 _debt) external pure returns (uint);
function collateralAddress() external view returns(address);
}
文件 6 的 24:IDefaultPool.sol
pragma solidity ^0.8.17;
import "./IPool.sol";
interface IDefaultPool is IPool {
event TroveManagerAddressChanged(address _newTroveManagerAddress);
event DefaultPoolTHUSDDebtUpdated(uint256 _THUSDDebt);
event DefaultPoolCollateralBalanceUpdated(uint256 _collateral);
event CollateralAddressChanged(address _newCollateralAddress);
function sendCollateralToActivePool(uint256 _amount) external;
function updateCollateralBalance(uint256 _amount) external;
function collateralAddress() external view returns(address);
}
文件 7 的 24:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 8 的 24:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 24:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 10 的 24:IERC2612.sol
pragma solidity ^0.8.17;
interface IERC2612 {
function permit(address owner, address spender, uint256 amount,
uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
function nonces(address owner) external view returns (uint256);
function version() external view returns (string memory);
function permitTypeHash() external view returns (bytes32);
function domainSeparator() external view returns (bytes32);
}
文件 11 的 24:ILiquityBase.sol
pragma solidity ^0.8.17;
import "./IPriceFeed.sol";
interface ILiquityBase {
function priceFeed() external view returns (IPriceFeed);
}
文件 12 的 24:IPCV.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ITHUSDToken.sol";
interface IPCV {
event THUSDTokenAddressSet(address _thusdTokenAddress);
event BorrowerOperationsAddressSet(address _borrowerOperationsAddress);
event CollateralAddressSet(address _collateralAddress);
event BAMMAddressSet(address _bammAddress);
event RolesSet(address _council, address _treasury);
event BAMMDeposit(uint256 _thusdAmount);
event BAMMWithdraw(uint256 _numShares);
event THUSDWithdraw(address _recipient, uint256 _thusdAmount);
event CollateralWithdraw(address _recipient, uint256 _collateralAmount);
event PCVDebtPaid(uint256 _paidDebt);
event RecipientAdded(address _recipient);
event RecipientRemoved(address _recipient);
function debtToPay() external returns(uint256);
function payDebt(uint256 _thusdToBurn) external;
function setAddresses(
address _thusdTokenAddress,
address _borrowerOperations,
address payable _bammAddress,
address _collateralERC20
) external;
function initialize() external;
function depositToBAMM(uint256 _thusdAmount) external;
function withdrawFromBAMM(uint256 _numShares) external;
function withdrawTHUSD(address _recipient, uint256 _thusdAmount) external;
function withdrawCollateral(address _recipient, uint256 _collateralAmount) external;
function addRecipientToWhitelist(address _recipient) external;
function addRecipientsToWhitelist(address[] calldata _recipients) external;
function removeRecipientFromWhitelist(address _recipient) external;
function removeRecipientsFromWhitelist(address[] calldata _recipients) external;
function startChangingRoles(address _council, address _treasury) external;
function cancelChangingRoles() external;
function finalizeChangingRoles() external;
function collateralERC20() external view returns(IERC20);
function thusdToken() external view returns(ITHUSDToken);
}
文件 13 的 24:IPool.sol
pragma solidity ^0.8.17;
interface IPool {
event CollateralBalanceUpdated(uint256 _newBalance);
event THUSDBalanceUpdated(uint256 _newBalance);
event ActivePoolAddressChanged(address _newActivePoolAddress);
event DefaultPoolAddressChanged(address _newDefaultPoolAddress);
event StabilityPoolAddressChanged(address _newStabilityPoolAddress);
event CollateralSent(address _to, uint256 _amount);
function getCollateralBalance() external view returns (uint);
function getTHUSDDebt() external view returns (uint);
function increaseTHUSDDebt(uint256 _amount) external;
function decreaseTHUSDDebt(uint256 _amount) external;
}
文件 14 的 24:IPriceFeed.sol
pragma solidity ^0.8.17;
interface IPriceFeed {
event LastGoodPriceUpdated(uint256 _lastGoodPrice);
function fetchPrice() external returns (uint);
}
文件 15 的 24:ISortedTroves.sol
pragma solidity ^0.8.17;
interface ISortedTroves {
event SortedTrovesAddressChanged(address _sortedDoublyLLAddress);
event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress);
event NodeAdded(address _id, uint256 _NICR);
event NodeRemoved(address _id);
function setParams(uint256 _size, address _TroveManagerAddress, address _borrowerOperationsAddress) external;
function insert(address _id, uint256 _ICR, address _prevId, address _nextId) external;
function remove(address _id) external;
function reInsert(address _id, uint256 _newICR, address _prevId, address _nextId) external;
function contains(address _id) external view returns (bool);
function isFull() external view returns (bool);
function isEmpty() external view returns (bool);
function getSize() external view returns (uint256);
function getMaxSize() external view returns (uint256);
function getFirst() external view returns (address);
function getLast() external view returns (address);
function getNext(address _id) external view returns (address);
function getPrev(address _id) external view returns (address);
function validInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (bool);
function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address);
}
文件 16 的 24:IStabilityPool.sol
pragma solidity ^0.8.17;
interface IStabilityPool {
event StabilityPoolCollateralBalanceUpdated(uint256 _newBalance);
event StabilityPoolTHUSDBalanceUpdated(uint256 _newBalance);
event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
event TroveManagerAddressChanged(address _newTroveManagerAddress);
event ActivePoolAddressChanged(address _newActivePoolAddress);
event DefaultPoolAddressChanged(address _newDefaultPoolAddress);
event THUSDTokenAddressChanged(address _newTHUSDTokenAddress);
event SortedTrovesAddressChanged(address _newSortedTrovesAddress);
event PriceFeedAddressChanged(address _newPriceFeedAddress);
event CollateralAddressChanged(address _newCollateralAddress);
event P_Updated(uint256 _P);
event S_Updated(uint256 _S, uint128 _epoch, uint128 _scale);
event EpochUpdated(uint128 _currentEpoch);
event ScaleUpdated(uint128 _currentScale);
event DepositSnapshotUpdated(address indexed _depositor, uint256 _P, uint256 _S);
event UserDepositChanged(address indexed _depositor, uint256 _newDeposit);
event CollateralGainWithdrawn(address indexed _depositor, uint256 _collateral, uint256 _THUSDLoss);
event CollateralSent(address _to, uint256 _amount);
function setAddresses(
address _borrowerOperationsAddress,
address _troveManagerAddress,
address _activePoolAddress,
address _thusdTokenAddress,
address _sortedTrovesAddress,
address _priceFeedAddress,
address _collateralAddress
) external;
function provideToSP(uint256 _amount) external;
function withdrawFromSP(uint256 _amount) external;
function withdrawCollateralGainToTrove(address _upperHint, address _lowerHint) external;
function offset(uint256 _debt, uint256 _coll) external;
function getCollateralBalance() external view returns (uint);
function getTotalTHUSDDeposits() external view returns (uint);
function getDepositorCollateralGain(address _depositor) external view returns (uint);
function getCompoundedTHUSDDeposit(address _depositor) external view returns (uint);
function updateCollateralBalance(uint256 _amount) external;
function collateralAddress() external view returns(address);
}
文件 17 的 24:ITHUSDToken.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "../Dependencies/IERC2612.sol";
interface ITHUSDToken is IERC20Metadata, IERC2612 {
event TroveManagerAddressAdded(address _troveManagerAddress);
event StabilityPoolAddressAdded(address _newStabilityPoolAddress);
event BorrowerOperationsAddressAdded(address _newBorrowerOperationsAddress);
event THUSDTokenBalanceUpdated(address _user, uint256 _amount);
function mintList(address contractAddress) external view returns (bool);
function burnList(address contractAddress) external view returns (bool);
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
}
文件 18 的 24:ITroveManager.sol
pragma solidity ^0.8.17;
import "./ILiquityBase.sol";
import "./IStabilityPool.sol";
import "./ITHUSDToken.sol";
import "./IPCV.sol";
interface ITroveManager is ILiquityBase {
enum Status {
nonExistent,
active,
closedByOwner,
closedByLiquidation,
closedByRedemption
}
event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
event PriceFeedAddressChanged(address _newPriceFeedAddress);
event THUSDTokenAddressChanged(address _newTHUSDTokenAddress);
event ActivePoolAddressChanged(address _activePoolAddress);
event DefaultPoolAddressChanged(address _defaultPoolAddress);
event StabilityPoolAddressChanged(address _stabilityPoolAddress);
event GasPoolAddressChanged(address _gasPoolAddress);
event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
event SortedTrovesAddressChanged(address _sortedTrovesAddress);
event PCVAddressChanged(address _pcvAddress);
event Liquidation(uint256 _liquidatedDebt, uint256 _liquidatedColl, uint256 _collGasCompensation, uint256 _THUSDGasCompensation);
event Redemption(uint256 _attemptedTHUSDAmount, uint256 _actualTHUSDAmount, uint256 _collateralSent, uint256 _collateralFee);
event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 stake, uint8 operation);
event TroveLiquidated(address indexed _borrower, uint256 _debt, uint256 _coll, uint8 operation);
event BaseRateUpdated(uint256 _baseRate);
event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);
event TotalStakesUpdated(uint256 _newTotalStakes);
event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);
event LTermsUpdated(uint256 _L_Collateral, uint256 _L_THUSDDebt);
event TroveSnapshotsUpdated(uint256 _L_Collateral, uint256 _L_THUSDDebt);
event TroveIndexUpdated(address _borrower, uint256 _newIndex);
function setAddresses(
address _borrowerOperationsAddress,
address _activePoolAddress,
address _defaultPoolAddress,
address _stabilityPoolAddress,
address _gasPoolAddress,
address _collSurplusPoolAddress,
address _priceFeedAddress,
address _thusdTokenAddress,
address _sortedTrovesAddress,
address _pcvAddress
) external;
function stabilityPool() external view returns (IStabilityPool);
function thusdToken() external view returns (ITHUSDToken);
function pcv() external view returns (IPCV);
function getTroveOwnersCount() external view returns (uint);
function getTroveFromTroveOwnersArray(uint256 _index) external view returns (address);
function getNominalICR(address _borrower) external view returns (uint);
function getCurrentICR(address _borrower, uint256 _price) external view returns (uint);
function liquidate(address _borrower) external;
function liquidateTroves(uint256 _n) external;
function batchLiquidateTroves(address[] calldata _troveArray) external;
function redeemCollateral(
uint256 _THUSDAmount,
address _firstRedemptionHint,
address _upperPartialRedemptionHint,
address _lowerPartialRedemptionHint,
uint256 _partialRedemptionHintNICR,
uint256 _maxIterations,
uint256 _maxFee
) external;
function updateStakeAndTotalStakes(address _borrower) external returns (uint);
function updateTroveRewardSnapshots(address _borrower) external;
function addTroveOwnerToArray(address _borrower) external returns (uint256 index);
function applyPendingRewards(address _borrower) external;
function getPendingCollateralReward(address _borrower) external view returns (uint);
function getPendingTHUSDDebtReward(address _borrower) external view returns (uint);
function hasPendingRewards(address _borrower) external view returns (bool);
function getEntireDebtAndColl(address _borrower) external view returns (
uint256 debt,
uint256 coll,
uint256 pendingTHUSDDebtReward,
uint256 pendingCollateralReward
);
function closeTrove(address _borrower) external;
function removeStake(address _borrower) external;
function getRedemptionRate() external view returns (uint);
function getRedemptionRateWithDecay() external view returns (uint);
function getRedemptionFeeWithDecay(uint256 _collateralDrawn) external view returns (uint);
function getBorrowingRate() external view returns (uint);
function getBorrowingRateWithDecay() external view returns (uint);
function getBorrowingFee(uint256 THUSDDebt) external view returns (uint);
function getBorrowingFeeWithDecay(uint256 _THUSDDebt) external view returns (uint);
function decayBaseRateFromBorrowing() external;
function getTroveStatus(address _borrower) external view returns (Status);
function getTroveStake(address _borrower) external view returns (uint);
function getTroveDebt(address _borrower) external view returns (uint);
function getTroveColl(address _borrower) external view returns (uint);
function setTroveStatus(address _borrower, Status _status) external;
function increaseTroveColl(address _borrower, uint256 _collIncrease) external returns (uint);
function decreaseTroveColl(address _borrower, uint256 _collDecrease) external returns (uint);
function increaseTroveDebt(address _borrower, uint256 _debtIncrease) external returns (uint);
function decreaseTroveDebt(address _borrower, uint256 _collDecrease) external returns (uint);
function getTCR(uint256 _price) external view returns (uint);
function checkRecoveryMode(uint256 _price) external view returns (bool);
}
文件 19 的 24:LiquityBase.sol
pragma solidity ^0.8.17;
import "./BaseMath.sol";
import "./LiquityMath.sol";
import "../Interfaces/IActivePool.sol";
import "../Interfaces/IDefaultPool.sol";
import "../Interfaces/IPriceFeed.sol";
import "../Interfaces/ILiquityBase.sol";
contract LiquityBase is BaseMath, ILiquityBase {
uint256 constant public _100pct = 1e18;
uint256 constant public MCR = 1.1e18;
uint256 constant public CCR = 1.5e18;
uint256 constant public THUSD_GAS_COMPENSATION = 200e18;
uint256 constant public MIN_NET_DEBT = 1800e18;
uint256 constant public PERCENT_DIVISOR = 200;
uint256 constant public BORROWING_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5;
IActivePool public activePool;
IDefaultPool public defaultPool;
IPriceFeed public override priceFeed;
function _getCompositeDebt(uint256 _debt) internal pure returns (uint) {
return _debt + THUSD_GAS_COMPENSATION;
}
function _getNetDebt(uint256 _debt) internal pure returns (uint) {
return _debt - THUSD_GAS_COMPENSATION;
}
function _getCollGasCompensation(uint256 _entireColl) internal pure returns (uint) {
return _entireColl / PERCENT_DIVISOR;
}
function getEntireSystemColl() public view returns (uint256 entireSystemColl) {
uint256 activeColl = activePool.getCollateralBalance();
uint256 liquidatedColl = defaultPool.getCollateralBalance();
return activeColl + liquidatedColl;
}
function getEntireSystemDebt() public view returns (uint256 entireSystemDebt) {
uint256 activeDebt = activePool.getTHUSDDebt();
uint256 closedDebt = defaultPool.getTHUSDDebt();
return activeDebt + closedDebt;
}
function _getTCR(uint256 _price) internal view returns (uint256 TCR) {
uint256 entireSystemColl = getEntireSystemColl();
uint256 entireSystemDebt = getEntireSystemDebt();
TCR = LiquityMath._computeCR(entireSystemColl, entireSystemDebt, _price);
return TCR;
}
function _checkRecoveryMode(uint256 _price) internal view returns (bool) {
uint256 TCR = _getTCR(_price);
return TCR < CCR;
}
function _requireUserAcceptsFee(uint256 _fee, uint256 _amount, uint256 _maxFeePercentage) internal pure {
uint256 feePercentage = _fee * DECIMAL_PRECISION / _amount;
require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum");
}
}
文件 20 的 24:LiquityMath.sol
pragma solidity ^0.8.17;
library LiquityMath {
uint256 internal constant DECIMAL_PRECISION = 1e18;
uint256 internal constant NICR_PRECISION = 1e20;
function _min(uint256 _a, uint256 _b) internal pure returns (uint) {
return (_a < _b) ? _a : _b;
}
function _max(uint256 _a, uint256 _b) internal pure returns (uint) {
return (_a >= _b) ? _a : _b;
}
function decMul(uint256 x, uint256 y) internal pure returns (uint256 decProd) {
uint256 prod_xy = x * y;
decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / DECIMAL_PRECISION;
}
function _decPow(uint256 _base, uint256 _minutes) internal pure returns (uint) {
if (_minutes > 525600000) {_minutes = 525600000;}
if (_minutes == 0) {return DECIMAL_PRECISION;}
uint256 y = DECIMAL_PRECISION;
uint256 x = _base;
uint256 n = _minutes;
while (n > 1) {
if (n % 2 == 0) {
x = decMul(x, x);
n = n / 2;
} else {
y = decMul(x, y);
x = decMul(x, x);
n = (n - 1) / 2;
}
}
return decMul(x, y);
}
function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint) {
return (_a >= _b) ? _a - _b : _b - _a;
}
function _computeNominalCR(uint256 _coll, uint256 _debt) internal pure returns (uint) {
if (_debt > 0) {
return _coll * NICR_PRECISION / _debt;
}
else {
return type(uint256).max;
}
}
function _computeCR(uint256 _coll, uint256 _debt, uint256 _price) internal pure returns (uint) {
if (_debt > 0) {
uint256 newCollRatio = _coll * _price / _debt;
return newCollRatio;
}
else {
return type(uint256).max;
}
}
}
文件 21 的 24:Ownable.sol
pragma solidity ^0.8.17;
contract Ownable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
function _renounceOwnership() internal {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 22 的 24:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 23 的 24:SendCollateral.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract SendCollateral {
using SafeERC20 for IERC20;
function sendCollateral(IERC20 _collateralERC20, address _recipient, uint256 _amount) internal {
if (address(_collateralERC20) == address(0)) {
(bool success, ) = _recipient.call{ value: _amount }("");
require(success, "Sending ETH failed");
} else {
_collateralERC20.safeTransfer(_recipient, _amount);
}
}
function sendCollateralFrom(IERC20 _collateralERC20, address _from, address _recipient, uint256 _amount) internal {
if (address(_collateralERC20) == address(0)) {
(bool success, ) = _recipient.call{ value: _amount }("");
require(success, "Sending ETH failed");
} else {
_collateralERC20.safeTransferFrom(_from, _recipient, _amount);
}
}
}
文件 24 的 24:StabilityPool.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import './Interfaces/IBorrowerOperations.sol';
import './Interfaces/IStabilityPool.sol';
import './Interfaces/IBorrowerOperations.sol';
import './Interfaces/ITroveManager.sol';
import './Interfaces/ITHUSDToken.sol';
import './Interfaces/ISortedTroves.sol';
import "./Dependencies/LiquityBase.sol";
import "./Dependencies/Ownable.sol";
import "./Dependencies/CheckContract.sol";
import "./Dependencies/SendCollateral.sol";
contract StabilityPool is LiquityBase, Ownable, CheckContract, SendCollateral, IStabilityPool {
string constant public NAME = "StabilityPool";
address public collateralAddress;
IBorrowerOperations public borrowerOperations;
ITroveManager public troveManager;
ITHUSDToken public thusdToken;
ISortedTroves public sortedTroves;
uint256 internal collateral;
uint256 internal totalTHUSDDeposits;
struct Snapshots {
uint256 S;
uint256 P;
uint128 scale;
uint128 epoch;
}
mapping (address => uint256) public deposits;
mapping (address => Snapshots) public depositSnapshots;
uint256 public P = DECIMAL_PRECISION;
uint256 public constant SCALE_FACTOR = 1e9;
uint128 public currentScale;
uint128 public currentEpoch;
mapping (uint128 => mapping(uint128 => uint)) public epochToScaleToSum;
uint256 public lastCollateralError_Offset;
uint256 public lastTHUSDLossError_Offset;
function setAddresses(
address _borrowerOperationsAddress,
address _troveManagerAddress,
address _activePoolAddress,
address _thusdTokenAddress,
address _sortedTrovesAddress,
address _priceFeedAddress,
address _collateralAddress
)
external
override
onlyOwner
{
checkContract(_borrowerOperationsAddress);
checkContract(_troveManagerAddress);
checkContract(_activePoolAddress);
checkContract(_thusdTokenAddress);
checkContract(_sortedTrovesAddress);
checkContract(_priceFeedAddress);
if (_collateralAddress != address(0)) {
checkContract(_collateralAddress);
}
borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);
troveManager = ITroveManager(_troveManagerAddress);
activePool = IActivePool(_activePoolAddress);
thusdToken = ITHUSDToken(_thusdTokenAddress);
sortedTroves = ISortedTroves(_sortedTrovesAddress);
priceFeed = IPriceFeed(_priceFeedAddress);
collateralAddress = _collateralAddress;
require(
(Ownable(_borrowerOperationsAddress).owner() != address(0) ||
borrowerOperations.collateralAddress() == _collateralAddress) &&
(Ownable(_activePoolAddress).owner() != address(0) ||
activePool.collateralAddress() == _collateralAddress),
"The same collateral address must be used for the entire set of contracts"
);
emit BorrowerOperationsAddressChanged(_borrowerOperationsAddress);
emit TroveManagerAddressChanged(_troveManagerAddress);
emit ActivePoolAddressChanged(_activePoolAddress);
emit THUSDTokenAddressChanged(_thusdTokenAddress);
emit SortedTrovesAddressChanged(_sortedTrovesAddress);
emit PriceFeedAddressChanged(_priceFeedAddress);
emit CollateralAddressChanged(_collateralAddress);
_renounceOwnership();
}
function getCollateralBalance() external view override returns (uint) {
return collateral;
}
function getTotalTHUSDDeposits() external view override returns (uint) {
return totalTHUSDDeposits;
}
function provideToSP(uint256 _amount) external override {
_requireNonZeroAmount(_amount);
uint256 initialDeposit = deposits[msg.sender];
uint256 depositorCollateralGain = getDepositorCollateralGain(msg.sender);
uint256 compoundedTHUSDDeposit = getCompoundedTHUSDDeposit(msg.sender);
uint256 THUSDLoss = initialDeposit - compoundedTHUSDDeposit;
_sendTHUSDtoStabilityPool(msg.sender, _amount);
uint256 newDeposit = compoundedTHUSDDeposit + _amount;
_updateDepositAndSnapshots(msg.sender, newDeposit);
emit UserDepositChanged(msg.sender, newDeposit);
emit CollateralGainWithdrawn(msg.sender, depositorCollateralGain, THUSDLoss);
_sendCollateralGainToDepositor(depositorCollateralGain);
}
function withdrawFromSP(uint256 _amount) external override {
if (_amount !=0) {_requireNoUnderCollateralizedTroves();}
uint256 initialDeposit = deposits[msg.sender];
_requireUserHasDeposit(initialDeposit);
uint256 depositorCollateralGain = getDepositorCollateralGain(msg.sender);
uint256 compoundedTHUSDDeposit = getCompoundedTHUSDDeposit(msg.sender);
uint256 THUSDtoWithdraw = LiquityMath._min(_amount, compoundedTHUSDDeposit);
uint256 THUSDLoss = initialDeposit - compoundedTHUSDDeposit;
_sendTHUSDToDepositor(msg.sender, THUSDtoWithdraw);
uint256 newDeposit = compoundedTHUSDDeposit - THUSDtoWithdraw;
_updateDepositAndSnapshots(msg.sender, newDeposit);
emit UserDepositChanged(msg.sender, newDeposit);
emit CollateralGainWithdrawn(msg.sender, depositorCollateralGain, THUSDLoss);
_sendCollateralGainToDepositor(depositorCollateralGain);
}
function withdrawCollateralGainToTrove(address _upperHint, address _lowerHint) external override {
uint256 initialDeposit = deposits[msg.sender];
_requireUserHasDeposit(initialDeposit);
_requireUserHasTrove(msg.sender);
_requireUserHasCollateralGain(msg.sender);
uint256 depositorCollateralGain = getDepositorCollateralGain(msg.sender);
uint256 compoundedTHUSDDeposit = getCompoundedTHUSDDeposit(msg.sender);
uint256 THUSDLoss = initialDeposit - compoundedTHUSDDeposit;
_updateDepositAndSnapshots(msg.sender, compoundedTHUSDDeposit);
emit CollateralGainWithdrawn(msg.sender, depositorCollateralGain, THUSDLoss);
emit UserDepositChanged(msg.sender, compoundedTHUSDDeposit);
collateral -= depositorCollateralGain;
emit StabilityPoolCollateralBalanceUpdated(collateral);
emit CollateralSent(msg.sender, depositorCollateralGain);
if (collateralAddress == address(0)) {
borrowerOperations.moveCollateralGainToTrove{ value: depositorCollateralGain }(msg.sender, 0, _upperHint, _lowerHint);
} else {
borrowerOperations.moveCollateralGainToTrove{ value: 0 }(msg.sender, depositorCollateralGain, _upperHint, _lowerHint);
}
}
function offset(uint256 _debtToOffset, uint256 _collToAdd) external override {
_requireCallerIsTroveManager();
uint256 totalTHUSD = totalTHUSDDeposits;
if (totalTHUSD == 0 || _debtToOffset == 0) { return; }
(uint256 collateralGainPerUnitStaked,
uint256 THUSDLossPerUnitStaked) = _computeRewardsPerUnitStaked(_collToAdd, _debtToOffset, totalTHUSD);
_updateRewardSumAndProduct(collateralGainPerUnitStaked, THUSDLossPerUnitStaked);
_moveOffsetCollAndDebt(_collToAdd, _debtToOffset);
}
function _computeRewardsPerUnitStaked(
uint256 _collToAdd,
uint256 _debtToOffset,
uint256 _totalTHUSDDeposits
)
internal
returns (uint256 collateralGainPerUnitStaked, uint256 THUSDLossPerUnitStaked)
{
uint256 collateralNumerator = _collToAdd * DECIMAL_PRECISION + lastCollateralError_Offset;
assert(_debtToOffset <= _totalTHUSDDeposits);
if (_debtToOffset == _totalTHUSDDeposits) {
THUSDLossPerUnitStaked = DECIMAL_PRECISION;
lastTHUSDLossError_Offset = 0;
} else {
uint256 THUSDLossNumerator = _debtToOffset * DECIMAL_PRECISION - lastTHUSDLossError_Offset;
THUSDLossPerUnitStaked = THUSDLossNumerator / _totalTHUSDDeposits + 1;
lastTHUSDLossError_Offset = THUSDLossPerUnitStaked * _totalTHUSDDeposits - THUSDLossNumerator;
}
collateralGainPerUnitStaked = collateralNumerator / _totalTHUSDDeposits;
lastCollateralError_Offset = collateralNumerator - (collateralGainPerUnitStaked * _totalTHUSDDeposits);
return (collateralGainPerUnitStaked, THUSDLossPerUnitStaked);
}
function _updateRewardSumAndProduct(uint256 _collateralGainPerUnitStaked, uint256 _THUSDLossPerUnitStaked) internal {
uint256 currentP = P;
uint256 newP;
assert(_THUSDLossPerUnitStaked <= DECIMAL_PRECISION);
uint256 newProductFactor = DECIMAL_PRECISION - _THUSDLossPerUnitStaked;
uint128 currentScaleCached = currentScale;
uint128 currentEpochCached = currentEpoch;
uint256 currentS = epochToScaleToSum[currentEpochCached][currentScaleCached];
uint256 marginalCollateralGain = _collateralGainPerUnitStaked * currentP;
uint256 newS = currentS + marginalCollateralGain;
epochToScaleToSum[currentEpochCached][currentScaleCached] = newS;
emit S_Updated(newS, currentEpochCached, currentScaleCached);
if (newProductFactor == 0) {
currentEpoch = currentEpochCached + 1;
emit EpochUpdated(currentEpoch);
currentScale = 0;
emit ScaleUpdated(currentScale);
newP = DECIMAL_PRECISION;
} else if (currentP * newProductFactor / DECIMAL_PRECISION < SCALE_FACTOR) {
newP = currentP * newProductFactor * SCALE_FACTOR / DECIMAL_PRECISION;
currentScale = currentScaleCached + 1;
emit ScaleUpdated(currentScale);
} else {
newP = currentP * newProductFactor / DECIMAL_PRECISION;
}
assert(newP > 0);
P = newP;
emit P_Updated(newP);
}
function _moveOffsetCollAndDebt(uint256 _collToAdd, uint256 _debtToOffset) internal {
IActivePool activePoolCached = activePool;
activePoolCached.decreaseTHUSDDebt(_debtToOffset);
_decreaseTHUSD(_debtToOffset);
thusdToken.burn(address(this), _debtToOffset);
activePoolCached.sendCollateral(address(this), _collToAdd);
}
function _decreaseTHUSD(uint256 _amount) internal {
uint256 newTotalTHUSDDeposits = totalTHUSDDeposits - _amount;
totalTHUSDDeposits = newTotalTHUSDDeposits;
emit StabilityPoolTHUSDBalanceUpdated(newTotalTHUSDDeposits);
}
function getDepositorCollateralGain(address _depositor) public view override returns (uint) {
uint256 initialDeposit = deposits[_depositor];
if (initialDeposit == 0) { return 0; }
Snapshots memory snapshots = depositSnapshots[_depositor];
uint256 collateralGain = _getCollateralGainFromSnapshots(initialDeposit, snapshots);
return collateralGain;
}
function _getCollateralGainFromSnapshots(uint256 initialDeposit, Snapshots memory snapshots) internal view returns (uint) {
uint128 epochSnapshot = snapshots.epoch;
uint128 scaleSnapshot = snapshots.scale;
uint256 S_Snapshot = snapshots.S;
uint256 P_Snapshot = snapshots.P;
uint256 firstPortion = epochToScaleToSum[epochSnapshot][scaleSnapshot] - S_Snapshot;
uint256 secondPortion = epochToScaleToSum[epochSnapshot][scaleSnapshot + 1] / SCALE_FACTOR;
uint256 collateralGain = initialDeposit * (firstPortion + secondPortion) / P_Snapshot / DECIMAL_PRECISION;
return collateralGain;
}
function getCompoundedTHUSDDeposit(address _depositor) public view override returns (uint) {
uint256 initialDeposit = deposits[_depositor];
if (initialDeposit == 0) { return 0; }
Snapshots memory snapshots = depositSnapshots[_depositor];
uint256 compoundedDeposit = _getCompoundedStakeFromSnapshots(initialDeposit, snapshots);
return compoundedDeposit;
}
function _getCompoundedStakeFromSnapshots(
uint256 initialStake,
Snapshots memory snapshots
)
internal
view
returns (uint)
{
uint256 snapshot_P = snapshots.P;
uint128 scaleSnapshot = snapshots.scale;
uint128 epochSnapshot = snapshots.epoch;
if (epochSnapshot < currentEpoch) { return 0; }
uint256 compoundedStake;
uint128 scaleDiff = currentScale - scaleSnapshot;
if (scaleDiff == 0) {
compoundedStake = initialStake * P / snapshot_P;
} else if (scaleDiff == 1) {
compoundedStake = initialStake * P / snapshot_P / SCALE_FACTOR;
} else {
compoundedStake = 0;
}
if (compoundedStake < initialStake / 1e9) {return 0;}
return compoundedStake;
}
function _sendTHUSDtoStabilityPool(address _address, uint256 _amount) internal {
thusdToken.transferFrom(_address, address(this), _amount);
uint256 newTotalTHUSDDeposits = totalTHUSDDeposits + _amount;
totalTHUSDDeposits = newTotalTHUSDDeposits;
emit StabilityPoolTHUSDBalanceUpdated(newTotalTHUSDDeposits);
}
function _sendCollateralGainToDepositor(uint256 _amount) internal {
if (_amount == 0) {return;}
uint256 newCollateral = collateral - _amount;
collateral = newCollateral;
emit StabilityPoolCollateralBalanceUpdated(newCollateral);
emit CollateralSent(msg.sender, _amount);
sendCollateral(IERC20(collateralAddress), msg.sender, _amount);
}
function _sendTHUSDToDepositor(address _depositor, uint256 THUSDWithdrawal) internal {
if (THUSDWithdrawal == 0) {return;}
thusdToken.transfer(_depositor, THUSDWithdrawal);
_decreaseTHUSD(THUSDWithdrawal);
}
function _updateDepositAndSnapshots(address _depositor, uint256 _newValue) internal {
deposits[_depositor] = _newValue;
if (_newValue == 0) {
delete depositSnapshots[_depositor];
emit DepositSnapshotUpdated(_depositor, 0, 0);
return;
}
uint128 currentScaleCached = currentScale;
uint128 currentEpochCached = currentEpoch;
uint256 currentP = P;
uint256 currentS = epochToScaleToSum[currentEpochCached][currentScaleCached];
depositSnapshots[_depositor].P = currentP;
depositSnapshots[_depositor].S = currentS;
depositSnapshots[_depositor].scale = currentScaleCached;
depositSnapshots[_depositor].epoch = currentEpochCached;
emit DepositSnapshotUpdated(_depositor, currentP, currentS);
}
function _requireCallerIsActivePool() internal view {
require( msg.sender == address(activePool), "StabilityPool: Caller is not ActivePool");
}
function _requireCallerIsTroveManager() internal view {
require(msg.sender == address(troveManager), "StabilityPool: Caller is not TroveManager");
}
function _requireNoUnderCollateralizedTroves() internal {
uint256 price = priceFeed.fetchPrice();
address lowestTrove = sortedTroves.getLast();
uint256 ICR = troveManager.getCurrentICR(lowestTrove, price);
require(ICR >= MCR, "StabilityPool: Cannot withdraw while there are troves with ICR < MCR");
}
function _requireUserHasDeposit(uint256 _initialDeposit) internal pure {
require(_initialDeposit > 0, 'StabilityPool: User must have a non-zero deposit');
}
function _requireNonZeroAmount(uint256 _amount) internal pure {
require(_amount > 0, 'StabilityPool: Amount must be non-zero');
}
function _requireUserHasTrove(address _depositor) internal view {
require(
troveManager.getTroveStatus(_depositor) == ITroveManager.Status.active,
"StabilityPool: caller must have an active trove to withdraw collateralGain to"
);
}
function _requireUserHasCollateralGain(address _depositor) internal view {
uint256 collateralGain = getDepositorCollateralGain(_depositor);
require(collateralGain > 0, "StabilityPool: caller must have non-zero collateral Gain");
}
function updateCollateralBalance(uint256 _amount) external override {
_requireCallerIsActivePool();
collateral += _amount;
emit StabilityPoolCollateralBalanceUpdated(collateral);
}
receive() external payable {
_requireCallerIsActivePool();
collateral += msg.value;
emit StabilityPoolCollateralBalanceUpdated(collateral);
}
}
{
"compilationTarget": {
"contracts/StabilityPool.sol": "StabilityPool"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newActivePoolAddress","type":"address"}],"name":"ActivePoolAddressChanged","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":"_newCollateralAddress","type":"address"}],"name":"CollateralAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_THUSDLoss","type":"uint256"}],"name":"CollateralGainWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"CollateralSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newDefaultPoolAddress","type":"address"}],"name":"DefaultPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_S","type":"uint256"}],"name":"DepositSnapshotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentEpoch","type":"uint128"}],"name":"EpochUpdated","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":"uint256","name":"_P","type":"uint256"}],"name":"P_Updated","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":"_S","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"_epoch","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"_scale","type":"uint128"}],"name":"S_Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentScale","type":"uint128"}],"name":"ScaleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newSortedTrovesAddress","type":"address"}],"name":"SortedTrovesAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"StabilityPoolCollateralBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"StabilityPoolTHUSDBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newTHUSDTokenAddress","type":"address"}],"name":"THUSDTokenAddressChanged","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":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newDeposit","type":"uint256"}],"name":"UserDepositChanged","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":"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":"P","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"THUSD_GAS_COMPENSATION","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":[],"name":"borrowerOperations","outputs":[{"internalType":"contract IBorrowerOperations","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentScale","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultPool","outputs":[{"internalType":"contract IDefaultPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositSnapshots","outputs":[{"internalType":"uint256","name":"S","type":"uint256"},{"internalType":"uint256","name":"P","type":"uint256"},{"internalType":"uint128","name":"scale","type":"uint128"},{"internalType":"uint128","name":"epoch","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"epochToScaleToSum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"getCompoundedTHUSDDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"getDepositorCollateralGain","outputs":[{"internalType":"uint256","name":"","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":[],"name":"getTotalTHUSDDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastCollateralError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTHUSDLossError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtToOffset","type":"uint256"},{"internalType":"uint256","name":"_collToAdd","type":"uint256"}],"name":"offset","outputs":[],"stateMutability":"nonpayable","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":"_amount","type":"uint256"}],"name":"provideToSP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"address","name":"_troveManagerAddress","type":"address"},{"internalType":"address","name":"_activePoolAddress","type":"address"},{"internalType":"address","name":"_thusdTokenAddress","type":"address"},{"internalType":"address","name":"_sortedTrovesAddress","type":"address"},{"internalType":"address","name":"_priceFeedAddress","type":"address"},{"internalType":"address","name":"_collateralAddress","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":"thusdToken","outputs":[{"internalType":"contract ITHUSDToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"troveManager","outputs":[{"internalType":"contract ITroveManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"updateCollateralBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"withdrawCollateralGainToTrove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFromSP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]