编译器
0.6.12+commit.27d51765
文件 1 的 19:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 19:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 19:CoreUtility.sol
pragma solidity >=0.6.10 <0.8.0;
import "@openzeppelin/contracts/math/SafeMath.sol";
abstract contract CoreUtility {
using SafeMath for uint256;
uint256 internal constant SETTLEMENT_TIME = 14 hours;
function _endOfWeek(uint256 timestamp) internal pure returns (uint256) {
return ((timestamp.add(1 weeks) - SETTLEMENT_TIME) / 1 weeks) * 1 weeks + SETTLEMENT_TIME;
}
}
文件 4 的 19:ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal virtual {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 5 的 19:IChessController.sol
pragma solidity >=0.6.10 <0.8.0;
interface IChessController {
function getFundRelativeWeight(address account, uint256 timestamp) external returns (uint256);
}
文件 6 的 19:IChessSchedule.sol
pragma solidity >=0.6.10 <0.8.0;
interface IChessSchedule {
function getWeeklySupply(uint256 timestamp) external view returns (uint256);
function getRate(uint256 timestamp) external view returns (uint256);
function mint(address account, uint256 amount) external;
function addMinter(address account) external;
}
文件 7 的 19:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 8 的 19:IFundV3.sol
pragma solidity >=0.6.10 <0.8.0;
pragma experimental ABIEncoderV2;
import "./ITwapOracleV2.sol";
interface IFundV3 {
struct Rebalance {
uint256 ratioB2Q;
uint256 ratioR2Q;
uint256 ratioBR;
uint256 timestamp;
}
function tokenUnderlying() external view returns (address);
function tokenQ() external view returns (address);
function tokenB() external view returns (address);
function tokenR() external view returns (address);
function tokenShare(uint256 tranche) external view returns (address);
function primaryMarket() external view returns (address);
function primaryMarketUpdateProposal() external view returns (address, uint256);
function strategy() external view returns (address);
function strategyUpdateProposal() external view returns (address, uint256);
function underlyingDecimalMultiplier() external view returns (uint256);
function twapOracle() external view returns (ITwapOracleV2);
function feeCollector() external view returns (address);
function endOfDay(uint256 timestamp) external pure returns (uint256);
function trancheTotalSupply(uint256 tranche) external view returns (uint256);
function trancheBalanceOf(uint256 tranche, address account) external view returns (uint256);
function trancheAllBalanceOf(address account) external view returns (uint256, uint256, uint256);
function trancheBalanceVersion(address account) external view returns (uint256);
function trancheAllowance(
uint256 tranche,
address owner,
address spender
) external view returns (uint256);
function trancheAllowanceVersion(
address owner,
address spender
) external view returns (uint256);
function trancheTransfer(
uint256 tranche,
address recipient,
uint256 amount,
uint256 version
) external;
function trancheTransferFrom(
uint256 tranche,
address sender,
address recipient,
uint256 amount,
uint256 version
) external;
function trancheApprove(
uint256 tranche,
address spender,
uint256 amount,
uint256 version
) external;
function getRebalanceSize() external view returns (uint256);
function getRebalance(uint256 index) external view returns (Rebalance memory);
function getRebalanceTimestamp(uint256 index) external view returns (uint256);
function currentDay() external view returns (uint256);
function splitRatio() external view returns (uint256);
function historicalSplitRatio(uint256 version) external view returns (uint256);
function fundActivityStartTime() external view returns (uint256);
function isFundActive(uint256 timestamp) external view returns (bool);
function getEquivalentTotalB() external view returns (uint256);
function getEquivalentTotalQ() external view returns (uint256);
function historicalEquivalentTotalB(uint256 timestamp) external view returns (uint256);
function historicalNavs(uint256 timestamp) external view returns (uint256 navB, uint256 navR);
function extrapolateNav(uint256 price) external view returns (uint256, uint256, uint256);
function doRebalance(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 index
) external view returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR);
function batchRebalance(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 fromIndex,
uint256 toIndex
) external view returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR);
function refreshBalance(address account, uint256 targetVersion) external;
function refreshAllowance(address owner, address spender, uint256 targetVersion) external;
function shareTransfer(address sender, address recipient, uint256 amount) external;
function shareTransferFrom(
address spender,
address sender,
address recipient,
uint256 amount
) external returns (uint256 newAllowance);
function shareIncreaseAllowance(
address sender,
address spender,
uint256 addedValue
) external returns (uint256 newAllowance);
function shareDecreaseAllowance(
address sender,
address spender,
uint256 subtractedValue
) external returns (uint256 newAllowance);
function shareApprove(address owner, address spender, uint256 amount) external;
function historicalUnderlying(uint256 timestamp) external view returns (uint256);
function getTotalUnderlying() external view returns (uint256);
function getStrategyUnderlying() external view returns (uint256);
function getTotalDebt() external view returns (uint256);
event RebalanceTriggered(
uint256 indexed index,
uint256 indexed day,
uint256 navSum,
uint256 navB,
uint256 navROrZero,
uint256 ratioB2Q,
uint256 ratioR2Q,
uint256 ratioBR
);
event Settled(uint256 indexed day, uint256 navB, uint256 navR, uint256 interestRate);
event InterestRateUpdated(uint256 baseInterestRate, uint256 floatingInterestRate);
event BalancesRebalanced(
address indexed account,
uint256 version,
uint256 balanceQ,
uint256 balanceB,
uint256 balanceR
);
event AllowancesRebalanced(
address indexed owner,
address indexed spender,
uint256 version,
uint256 allowanceQ,
uint256 allowanceB,
uint256 allowanceR
);
}
文件 9 的 19:ILiquidityGauge.sol
pragma solidity >=0.6.10 <0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface ILiquidityGauge is IERC20 {
function mint(address account, uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
function workingSupply() external view returns (uint256);
function workingBalanceOf(address account) external view returns (uint256);
function claimableRewards(
address account
)
external
returns (
uint256 chessAmount,
uint256 bonusAmount,
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount
);
function claimRewards(address account) external;
function distribute(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount,
uint256 version
) external;
}
文件 10 的 19:IStableSwap.sol
pragma solidity >=0.6.10 <0.8.0;
import "../interfaces/IFundV3.sol";
interface IStableSwapCore {
function getQuoteOut(uint256 baseIn) external view returns (uint256 quoteOut);
function getQuoteIn(uint256 baseOut) external view returns (uint256 quoteIn);
function getBaseOut(uint256 quoteIn) external view returns (uint256 baseOut);
function getBaseIn(uint256 quoteOut) external view returns (uint256 baseIn);
function buy(
uint256 version,
uint256 baseOut,
address recipient,
bytes calldata data
) external returns (uint256 realBaseOut);
function sell(
uint256 version,
uint256 quoteOut,
address recipient,
bytes calldata data
) external returns (uint256 realQuoteOut);
}
interface IStableSwap is IStableSwapCore {
function fund() external view returns (IFundV3);
function baseTranche() external view returns (uint256);
function baseAddress() external view returns (address);
function quoteAddress() external view returns (address);
function allBalances() external view returns (uint256, uint256);
function getOraclePrice() external view returns (uint256);
function getCurrentD() external view returns (uint256);
function getCurrentPriceOverOracle() external view returns (uint256);
function getCurrentPrice() external view returns (uint256);
function getPriceOverOracleIntegral() external view returns (uint256);
function addLiquidity(uint256 version, address recipient) external returns (uint256);
function removeLiquidity(
uint256 version,
uint256 lpIn,
uint256 minBaseOut,
uint256 minQuoteOut
) external returns (uint256 baseOut, uint256 quoteOut);
function removeLiquidityUnwrap(
uint256 version,
uint256 lpIn,
uint256 minBaseOut,
uint256 minQuoteOut
) external returns (uint256 baseOut, uint256 quoteOut);
function removeBaseLiquidity(
uint256 version,
uint256 lpIn,
uint256 minBaseOut
) external returns (uint256 baseOut);
function removeQuoteLiquidity(
uint256 version,
uint256 lpIn,
uint256 minQuoteOut
) external returns (uint256 quoteOut);
function removeQuoteLiquidityUnwrap(
uint256 version,
uint256 lpIn,
uint256 minQuoteOut
) external returns (uint256 quoteOut);
}
interface IStableSwapCoreInternalRevertExpected {
function getQuoteOut(uint256 baseIn) external returns (uint256 quoteOut);
function getQuoteIn(uint256 baseOut) external returns (uint256 quoteIn);
function getBaseOut(uint256 quoteIn) external returns (uint256 baseOut);
function getBaseIn(uint256 quoteOut) external returns (uint256 baseIn);
function buy(
uint256 version,
uint256 baseOut,
address recipient,
bytes calldata data
) external returns (uint256 realBaseOut);
function sell(
uint256 version,
uint256 quoteOut,
address recipient,
bytes calldata data
) external returns (uint256 realQuoteOut);
}
文件 11 的 19:ITrancheIndexV2.sol
pragma solidity >=0.6.10 <0.8.0;
abstract contract ITrancheIndexV2 {
uint256 internal constant TRANCHE_Q = 0;
uint256 internal constant TRANCHE_B = 1;
uint256 internal constant TRANCHE_R = 2;
uint256 internal constant TRANCHE_COUNT = 3;
}
文件 12 的 19:ITwapOracle.sol
pragma solidity >=0.6.10 <0.8.0;
interface ITwapOracle {
enum UpdateType {
PRIMARY,
SECONDARY,
OWNER,
CHAINLINK,
UNISWAP_V2
}
function getTwap(uint256 timestamp) external view returns (uint256);
}
文件 13 的 19:ITwapOracleV2.sol
pragma solidity >=0.6.10 <0.8.0;
import "./ITwapOracle.sol";
interface ITwapOracleV2 is ITwapOracle {
function getLatest() external view returns (uint256);
}
文件 14 的 19:IVotingEscrow.sol
pragma solidity >=0.6.10 <0.8.0;
pragma experimental ABIEncoderV2;
interface IAddressWhitelist {
function check(address account) external view returns (bool);
}
interface IVotingEscrowCallback {
function syncWithVotingEscrow(address account) external;
}
interface IVotingEscrow {
struct LockedBalance {
uint256 amount;
uint256 unlockTime;
}
function token() external view returns (address);
function maxTime() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function totalSupply() external view returns (uint256);
function balanceOfAtTimestamp(
address account,
uint256 timestamp
) external view returns (uint256);
function getTimestampDropBelow(
address account,
uint256 threshold
) external view returns (uint256);
function getLockedBalance(address account) external view returns (LockedBalance memory);
}
文件 15 的 19:LiquidityGaugeV2.sol
pragma solidity >=0.6.10 <0.8.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../interfaces/ILiquidityGauge.sol";
import "../interfaces/IChessSchedule.sol";
import "../interfaces/IChessController.sol";
import "../interfaces/IFundV3.sol";
import "../interfaces/ITrancheIndexV2.sol";
import "../interfaces/IStableSwap.sol";
import "../interfaces/IVotingEscrow.sol";
import "../utils/CoreUtility.sol";
import "../utils/SafeDecimalMath.sol";
interface ISwapBonus {
function bonusToken() external view returns (address);
function getBonus() external returns (uint256);
}
contract LiquidityGaugeV2 is ILiquidityGauge, ITrancheIndexV2, CoreUtility, ERC20 {
using Math for uint256;
using SafeMath for uint256;
using SafeDecimalMath for uint256;
using SafeERC20 for IERC20;
struct Distribution {
uint256 amountQ;
uint256 amountB;
uint256 amountR;
uint256 quoteAmount;
}
uint256 private constant MAX_ITERATIONS = 500;
uint256 private constant MAX_BOOSTING_FACTOR = 3e18;
uint256 private constant MAX_BOOSTING_FACTOR_MINUS_ONE = MAX_BOOSTING_FACTOR - 1e18;
address public immutable stableSwap;
IERC20 private immutable _quoteToken;
IChessSchedule public immutable chessSchedule;
IChessController public immutable chessController;
IFundV3 public immutable fund;
IVotingEscrow private immutable _votingEscrow;
address public immutable swapBonus;
IERC20 private immutable _bonusToken;
uint256 private _workingSupply;
mapping(address => uint256) private _workingBalances;
uint256 public latestVersion;
mapping(uint256 => Distribution) public distributions;
mapping(uint256 => uint256) public distributionTotalSupplies;
mapping(address => Distribution) public userDistributions;
mapping(address => uint256) public userVersions;
uint256 private _chessIntegral;
uint256 private _chessIntegralTimestamp;
mapping(address => uint256) private _chessUserIntegrals;
mapping(address => uint256) private _claimableChess;
uint256 private _bonusIntegral;
mapping(address => uint256) private _bonusUserIntegral;
mapping(address => uint256) private _claimableBonus;
uint256 private _rate;
constructor(
string memory name_,
string memory symbol_,
address stableSwap_,
address chessSchedule_,
address chessController_,
address fund_,
address votingEscrow_,
address swapBonus_
) public ERC20(name_, symbol_) {
stableSwap = stableSwap_;
_quoteToken = IERC20(IStableSwap(stableSwap_).quoteAddress());
chessSchedule = IChessSchedule(chessSchedule_);
chessController = IChessController(chessController_);
fund = IFundV3(fund_);
_votingEscrow = IVotingEscrow(votingEscrow_);
swapBonus = swapBonus_;
_bonusToken = IERC20(ISwapBonus(swapBonus_).bonusToken());
_chessIntegralTimestamp = block.timestamp;
}
modifier onlyStableSwap() {
require(msg.sender == stableSwap, "Only stable swap");
_;
}
function getRate() external view returns (uint256) {
return _rate / 1e18;
}
function mint(address account, uint256 amount) external override onlyStableSwap {
uint256 oldWorkingBalance = _workingBalances[account];
uint256 oldWorkingSupply = _workingSupply;
uint256 oldBalance = balanceOf(account);
_checkpoint(account, oldBalance, oldWorkingBalance, oldWorkingSupply);
_mint(account, amount);
_updateWorkingBalance(account, oldWorkingBalance, oldWorkingSupply, oldBalance.add(amount));
}
function burnFrom(address account, uint256 amount) external override onlyStableSwap {
uint256 oldWorkingBalance = _workingBalances[account];
uint256 oldWorkingSupply = _workingSupply;
uint256 oldBalance = balanceOf(account);
_checkpoint(account, oldBalance, oldWorkingBalance, oldWorkingSupply);
_burn(account, amount);
_updateWorkingBalance(account, oldWorkingBalance, oldWorkingSupply, oldBalance.sub(amount));
}
function _transfer(address, address, uint256) internal override {
revert("Transfer is not allowed");
}
function workingBalanceOf(address account) external view override returns (uint256) {
return _workingBalances[account];
}
function workingSupply() external view override returns (uint256) {
return _workingSupply;
}
function claimableRewards(
address account
)
external
override
returns (
uint256 chessAmount,
uint256 bonusAmount,
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount
)
{
return _checkpoint(account, balanceOf(account), _workingBalances[account], _workingSupply);
}
function claimRewards(address account) external override {
uint256 balance = balanceOf(account);
uint256 oldWorkingBalance = _workingBalances[account];
uint256 oldWorkingSupply = _workingSupply;
(
uint256 chessAmount,
uint256 bonusAmount,
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount
) = _checkpoint(account, balance, oldWorkingBalance, oldWorkingSupply);
_updateWorkingBalance(account, oldWorkingBalance, oldWorkingSupply, balance);
if (chessAmount != 0) {
chessSchedule.mint(account, chessAmount);
delete _claimableChess[account];
}
if (bonusAmount != 0) {
_bonusToken.safeTransfer(account, bonusAmount);
delete _claimableBonus[account];
}
if (amountQ != 0 || amountB != 0 || amountR != 0 || quoteAmount != 0) {
uint256 version = latestVersion;
if (amountQ != 0) {
fund.trancheTransfer(TRANCHE_Q, account, amountQ, version);
}
if (amountB != 0) {
fund.trancheTransfer(TRANCHE_B, account, amountB, version);
}
if (amountR != 0) {
fund.trancheTransfer(TRANCHE_R, account, amountR, version);
}
if (quoteAmount != 0) {
_quoteToken.safeTransfer(account, quoteAmount);
}
delete userDistributions[account];
}
}
function syncWithVotingEscrow(address account) external {
uint256 balance = balanceOf(account);
uint256 oldWorkingBalance = _workingBalances[account];
uint256 oldWorkingSupply = _workingSupply;
_checkpoint(account, balance, oldWorkingBalance, oldWorkingSupply);
_updateWorkingBalance(account, oldWorkingBalance, oldWorkingSupply, balance);
}
function distribute(
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount,
uint256 version
) external override onlyStableSwap {
distributions[version].amountQ = amountQ;
distributions[version].amountB = amountB;
distributions[version].amountR = amountR;
distributions[version].quoteAmount = quoteAmount;
distributionTotalSupplies[version] = totalSupply();
latestVersion = version;
}
function _updateWorkingBalance(
address account,
uint256 oldWorkingBalance,
uint256 oldWorkingSupply,
uint256 newBalance
) private {
uint256 newWorkingBalance = newBalance;
uint256 veBalance = _votingEscrow.balanceOf(account);
if (veBalance > 0) {
uint256 veTotalSupply = _votingEscrow.totalSupply();
uint256 maxWorkingBalance = newWorkingBalance.multiplyDecimal(MAX_BOOSTING_FACTOR);
uint256 boostedWorkingBalance = newWorkingBalance.add(
totalSupply().mul(veBalance).multiplyDecimal(MAX_BOOSTING_FACTOR_MINUS_ONE).div(
veTotalSupply
)
);
newWorkingBalance = maxWorkingBalance.min(boostedWorkingBalance);
}
_workingSupply = oldWorkingSupply.sub(oldWorkingBalance).add(newWorkingBalance);
_workingBalances[account] = newWorkingBalance;
}
function _checkpoint(
address account,
uint256 balance,
uint256 weight,
uint256 totalWeight
)
private
returns (
uint256 chessAmount,
uint256 bonusAmount,
uint256 amountQ,
uint256 amountB,
uint256 amountR,
uint256 quoteAmount
)
{
chessAmount = _chessCheckpoint(account, weight, totalWeight);
bonusAmount = _bonusCheckpoint(account, weight, totalWeight);
(amountQ, amountB, amountR, quoteAmount) = _distributionCheckpoint(account, balance);
}
function _chessCheckpoint(
address account,
uint256 weight,
uint256 totalWeight
) private returns (uint256 amount) {
uint256 timestamp = _chessIntegralTimestamp;
uint256 integral = _chessIntegral;
uint256 endWeek = _endOfWeek(timestamp);
uint256 rate = _rate;
if (rate == 0) {
uint256 weeklySupply = chessSchedule.getWeeklySupply(timestamp);
if (weeklySupply != 0) {
rate = (weeklySupply / (endWeek - timestamp)).mul(
chessController.getFundRelativeWeight(address(this), timestamp)
);
}
}
for (uint256 i = 0; i < MAX_ITERATIONS && timestamp < block.timestamp; i++) {
uint256 endTimestamp = endWeek.min(block.timestamp);
if (totalWeight != 0) {
integral = integral.add(
rate.mul(endTimestamp - timestamp).decimalToPreciseDecimal().div(totalWeight)
);
}
if (endTimestamp == endWeek) {
rate = chessSchedule.getRate(endWeek).mul(
chessController.getFundRelativeWeight(address(this), endWeek)
);
endWeek += 1 weeks;
}
timestamp = endTimestamp;
}
_chessIntegralTimestamp = block.timestamp;
_chessIntegral = integral;
_rate = rate;
amount = _claimableChess[account].add(
weight.multiplyDecimalPrecise(integral.sub(_chessUserIntegrals[account]))
);
_claimableChess[account] = amount;
_chessUserIntegrals[account] = integral;
}
function _bonusCheckpoint(
address account,
uint256 weight,
uint256 totalWeight
) private returns (uint256 amount) {
uint256 newBonus = ISwapBonus(swapBonus).getBonus();
uint256 integral = _bonusIntegral;
if (totalWeight != 0 && newBonus != 0) {
integral = integral.add(newBonus.divideDecimalPrecise(totalWeight));
_bonusIntegral = integral;
}
uint256 oldUserIntegral = _bonusUserIntegral[account];
if (oldUserIntegral == integral) {
return _claimableBonus[account];
}
amount = _claimableBonus[account].add(
weight.multiplyDecimalPrecise(integral.sub(oldUserIntegral))
);
_claimableBonus[account] = amount;
_bonusUserIntegral[account] = integral;
}
function _distributionCheckpoint(
address account,
uint256 balance
) private returns (uint256 amountQ, uint256 amountB, uint256 amountR, uint256 quoteAmount) {
uint256 version = userVersions[account];
uint256 newVersion = latestVersion;
Distribution storage userDist = userDistributions[account];
amountQ = userDist.amountQ;
amountB = userDist.amountB;
amountR = userDist.amountR;
quoteAmount = userDist.quoteAmount;
if (version == newVersion) {
return (amountQ, amountB, amountR, quoteAmount);
}
for (uint256 i = version; i < newVersion; i++) {
if (amountQ != 0 || amountB != 0 || amountR != 0) {
(amountQ, amountB, amountR) = fund.doRebalance(amountQ, amountB, amountR, i);
}
Distribution storage dist = distributions[i + 1];
uint256 distTotalSupply = distributionTotalSupplies[i + 1];
if (distTotalSupply != 0) {
amountQ = amountQ.add(dist.amountQ.mul(balance).div(distTotalSupply));
amountB = amountB.add(dist.amountB.mul(balance).div(distTotalSupply));
amountR = amountR.add(dist.amountR.mul(balance).div(distTotalSupply));
quoteAmount = quoteAmount.add(dist.quoteAmount.mul(balance).div(distTotalSupply));
}
}
userDist.amountQ = amountQ;
userDist.amountB = amountB;
userDist.amountR = amountR;
userDist.quoteAmount = quoteAmount;
userVersions[account] = newVersion;
}
}
文件 16 的 19:Math.sol
pragma solidity >=0.6.0 <0.8.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 17 的 19:SafeDecimalMath.sol
pragma solidity >=0.6.10 <0.8.0;
import "@openzeppelin/contracts/math/SafeMath.sol";
library SafeDecimalMath {
using SafeMath for uint256;
uint256 private constant decimals = 18;
uint256 private constant highPrecisionDecimals = 27;
uint256 private constant UNIT = 10 ** uint256(decimals);
uint256 private constant PRECISE_UNIT = 10 ** uint256(highPrecisionDecimals);
uint256 private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR =
10 ** uint256(highPrecisionDecimals - decimals);
function multiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(y).div(UNIT);
}
function multiplyDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(y).div(PRECISE_UNIT);
}
function divideDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(UNIT).div(y);
}
function divideDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
return x.mul(PRECISE_UNIT).div(y);
}
function decimalToPreciseDecimal(uint256 i) internal pure returns (uint256) {
return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
}
function preciseDecimalToDecimal(uint256 i) internal pure returns (uint256) {
uint256 quotientTimesTen = i.mul(10).div(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen = quotientTimesTen.add(10);
}
return quotientTimesTen.div(10);
}
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
return c / a != b ? type(uint256).max : c;
}
function saturatingMultiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
return saturatingMul(x, y).div(UNIT);
}
}
文件 18 的 19:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
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 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 19 的 19:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/swap/LiquidityGaugeV2.sol": "LiquidityGaugeV2"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"stableSwap_","type":"address"},{"internalType":"address","name":"chessSchedule_","type":"address"},{"internalType":"address","name":"chessController_","type":"address"},{"internalType":"address","name":"fund_","type":"address"},{"internalType":"address","name":"votingEscrow_","type":"address"},{"internalType":"address","name":"swapBonus_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chessController","outputs":[{"internalType":"contract IChessController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chessSchedule","outputs":[{"internalType":"contract IChessSchedule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimableRewards","outputs":[{"internalType":"uint256","name":"chessAmount","type":"uint256"},{"internalType":"uint256","name":"bonusAmount","type":"uint256"},{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"distributionTotalSupplies","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"distributions","outputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fund","outputs":[{"internalType":"contract IFundV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stableSwap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapBonus","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"syncWithVotingEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userDistributions","outputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userVersions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"workingBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"workingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]