Compare commits
No commits in common. "4fb0b01e3c6d066bd37749049ef771dc0e1a9898" and "566bf34febb372df9f5c92889d8f0db926103168" have entirely different histories.
4fb0b01e3c
...
566bf34feb
@ -8,7 +8,6 @@ import {IERC20Metadata} from "@openzeppelin-contracts/token/ERC20/extensions/IER
|
|||||||
import {NoteKeeper} from "./types/NoteKeeper.sol";
|
import {NoteKeeper} from "./types/NoteKeeper.sol";
|
||||||
import {IBondDepository} from "./interfaces/IBondDepository.sol";
|
import {IBondDepository} from "./interfaces/IBondDepository.sol";
|
||||||
import {IWETH9} from "./interfaces/IWETH9.sol";
|
import {IWETH9} from "./interfaces/IWETH9.sol";
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
contract GhostBondDepository is IBondDepository, NoteKeeper {
|
contract GhostBondDepository is IBondDepository, NoteKeeper {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
@ -61,7 +60,7 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
if (price > maxPrice) revert DepositoryMaxPrice(price, maxPrice);
|
if (price > maxPrice) revert DepositoryMaxPrice(price, maxPrice);
|
||||||
|
|
||||||
expiry = term.fixedTerm ? term.vesting + currentTime : term.vesting;
|
expiry = term.fixedTerm ? term.vesting + currentTime : term.vesting;
|
||||||
payout = FullMath.mulDiv(amount, 1e18, price) / (10**metadatas[id].quoteDecimals);
|
payout = ((amount * 1e18) / price) / (10**metadatas[id].quoteDecimals);
|
||||||
if (payout > market.maxPayout) revert DepositoryMaxSize(payout, market.maxPayout);
|
if (payout > market.maxPayout) revert DepositoryMaxSize(payout, market.maxPayout);
|
||||||
|
|
||||||
market.capacity -= market.capacityInQuote ? amount : payout;
|
market.capacity -= market.capacityInQuote ? amount : payout;
|
||||||
@ -117,14 +116,14 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
uint256 price = _marketPrice(id);
|
uint256 price = _marketPrice(id);
|
||||||
|
|
||||||
uint256 capacity = market.capacityInQuote
|
uint256 capacity = market.capacityInQuote
|
||||||
? FullMath.mulDiv(market.capacity, 1e18, price) / (10**meta.quoteDecimals)
|
? ((market.capacity * 1e18) / price) / (10**meta.quoteDecimals)
|
||||||
: market.capacity;
|
: market.capacity;
|
||||||
|
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
markets[id].maxPayout = uint64(FullMath.mulDiv(capacity, meta.depositInterval, timeRemaining));
|
markets[id].maxPayout = uint64((capacity * meta.depositInterval) / timeRemaining);
|
||||||
uint256 targetDebt = FullMath.mulDiv(capacity, meta.length, timeRemaining);
|
uint256 targetDebt = (capacity * meta.length) / timeRemaining;
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
uint64 newControlVariable = uint64(FullMath.mulDiv(price, _treasury.baseSupply(), targetDebt));
|
uint64 newControlVariable = uint64((price * _treasury.baseSupply()) / targetDebt);
|
||||||
|
|
||||||
emit Tuned(id, terms[id].controlVariable, newControlVariable);
|
emit Tuned(id, terms[id].controlVariable, newControlVariable);
|
||||||
|
|
||||||
@ -158,13 +157,13 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
uint256 secondsToConclusion = _terms[1] - block.timestamp;
|
uint256 secondsToConclusion = _terms[1] - block.timestamp;
|
||||||
uint256 decimals = IERC20Metadata(_quoteToken).decimals();
|
uint256 decimals = IERC20Metadata(_quoteToken).decimals();
|
||||||
uint64 targetDebt = uint64(_booleans[0]
|
uint64 targetDebt = uint64(_booleans[0]
|
||||||
? FullMath.mulDiv(_market[0], 1e18, _market[1]) / 10**decimals
|
? ((_market[0] * 1e18) / _market[1]) / 10**decimals
|
||||||
: _market[0]);
|
: _market[0]);
|
||||||
|
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
uint64 maxPayout = uint64(FullMath.mulDiv(targetDebt, _intervals[0], secondsToConclusion));
|
uint64 maxPayout = uint64((targetDebt * _intervals[0]) / secondsToConclusion);
|
||||||
uint256 maxDebt = targetDebt + FullMath.mulDiv(targetDebt, _market[2], 1e5);
|
uint256 maxDebt = targetDebt + ((targetDebt * _market[2]) / 1e5);
|
||||||
uint256 controlVariable = FullMath.mulDiv(_market[1], _treasury.baseSupply(), targetDebt);
|
uint256 controlVariable = (_market[1] * _treasury.baseSupply()) / targetDebt;
|
||||||
|
|
||||||
id = markets.length;
|
id = markets.length;
|
||||||
|
|
||||||
@ -219,19 +218,21 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function marketPrice(uint256 id) public view override returns (uint256) {
|
function marketPrice(uint256 id) public view override returns (uint256) {
|
||||||
return FullMath.mulDiv(currentControlVariable(id), debtRatio(id), 10**metadatas[id].quoteDecimals);
|
uint256 nominator = currentControlVariable(id) * debtRatio(id);
|
||||||
|
return nominator / (10**metadatas[id].quoteDecimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
function payoutFor(
|
function payoutFor(
|
||||||
uint256 id,
|
uint256 id,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
) external view override returns (uint256) {
|
) external view override returns (uint256) {
|
||||||
uint256 nominator = FullMath.mulDiv(amount, 1e18, marketPrice(id));
|
uint256 nominator = (amount * 1e18) / marketPrice(id);
|
||||||
return nominator / 10**metadatas[id].quoteDecimals;
|
return nominator / 10**metadatas[id].quoteDecimals;
|
||||||
}
|
}
|
||||||
|
|
||||||
function debtRatio(uint256 id) public view override returns (uint256) {
|
function debtRatio(uint256 id) public view override returns (uint256) {
|
||||||
return FullMath.mulDiv(currentDebt(id), 10**metadatas[id].quoteDecimals, _treasury.baseSupply());
|
uint256 nominator = currentDebt(id) * (10**metadatas[id].quoteDecimals);
|
||||||
|
return nominator / _treasury.baseSupply();
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentDebt(uint256 id) public view override returns (uint256) {
|
function currentDebt(uint256 id) public view override returns (uint256) {
|
||||||
@ -241,7 +242,7 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
function debtDecay(uint256 id) public view override returns (uint64) {
|
function debtDecay(uint256 id) public view override returns (uint64) {
|
||||||
Metadata memory meta = metadatas[id];
|
Metadata memory meta = metadatas[id];
|
||||||
uint256 secondsSince = block.timestamp - meta.lastDecay;
|
uint256 secondsSince = block.timestamp - meta.lastDecay;
|
||||||
return uint64(FullMath.mulDiv(markets[id].totalDebt, secondsSince, meta.length));
|
return uint64((markets[id].totalDebt * secondsSince) / meta.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentControlVariable(uint256 id) public view override returns (uint256) {
|
function currentControlVariable(uint256 id) public view override returns (uint256) {
|
||||||
@ -305,11 +306,13 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _marketPrice(uint256 _id) internal view returns (uint256) {
|
function _marketPrice(uint256 _id) internal view returns (uint256) {
|
||||||
return FullMath.mulDiv(terms[_id].controlVariable, _debtRatio(_id), 10**metadatas[_id].quoteDecimals);
|
uint256 nominator = terms[_id].controlVariable * _debtRatio(_id);
|
||||||
|
return nominator / (10**metadatas[_id].quoteDecimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _debtRatio(uint256 id) internal view returns (uint256) {
|
function _debtRatio(uint256 id) internal view returns (uint256) {
|
||||||
return FullMath.mulDiv(markets[id].totalDebt, 10**metadatas[id].quoteDecimals, _treasury.baseSupply());
|
uint256 nominator = markets[id].totalDebt * (10**metadatas[id].quoteDecimals);
|
||||||
|
return nominator / _treasury.baseSupply();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _controlDecay(uint256 id)
|
function _controlDecay(uint256 id)
|
||||||
@ -328,8 +331,7 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
|
|
||||||
active = secondsSince < info.timeToAdjusted;
|
active = secondsSince < info.timeToAdjusted;
|
||||||
decay = active
|
decay = active
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
? (info.change * secondsSince) / info.timeToAdjusted
|
||||||
? uint64(FullMath.mulDiv(info.change, secondsSince, info.timeToAdjusted))
|
|
||||||
: info.change;
|
: info.change;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import {Nonces} from "@openzeppelin-contracts/utils/Nonces.sol";
|
|||||||
|
|
||||||
import {ISTNK} from "./interfaces/ISTNK.sol";
|
import {ISTNK} from "./interfaces/ISTNK.sol";
|
||||||
import {IGHST} from "./interfaces/IGHST.sol";
|
import {IGHST} from "./interfaces/IGHST.sol";
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
|
contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
|
||||||
address public override staking;
|
address public override staking;
|
||||||
@ -61,11 +60,11 @@ contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function balanceFrom(uint256 _amount) public view override returns (uint256) {
|
function balanceFrom(uint256 _amount) public view override returns (uint256) {
|
||||||
return FullMath.mulDiv(_amount, index(), 1e18);
|
return _amount * index() / 1e18;
|
||||||
}
|
}
|
||||||
|
|
||||||
function balanceTo(uint256 _amount) public view override returns (uint256) {
|
function balanceTo(uint256 _amount) public view override returns (uint256) {
|
||||||
return FullMath.mulDiv(_amount, 1e18, index());
|
return _amount * 1e18 / index();
|
||||||
}
|
}
|
||||||
|
|
||||||
function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
|
function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
} else {
|
} else {
|
||||||
if (locks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
if (locks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
||||||
uint48 expiry = epoch.number + warmupPeriod;
|
uint48 expiry = epoch.number + warmupPeriod;
|
||||||
IGhostWarmup(warmup).addToWarmup(returnAmount, to, expiry);
|
IGhostWarmup(warmup).addToWarmup(amount, to, expiry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import {IERC20} from "@openzeppelin-contracts/token/ERC20/IERC20.sol";
|
|||||||
import {IUniswapV2Pair} from "@uniswap-v2-core/interfaces/IUniswapV2Pair.sol";
|
import {IUniswapV2Pair} from "@uniswap-v2-core/interfaces/IUniswapV2Pair.sol";
|
||||||
|
|
||||||
import {GhostAccessControlled} from "./types/GhostAccessControlled.sol";
|
import {GhostAccessControlled} from "./types/GhostAccessControlled.sol";
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
import {ITreasury} from "./interfaces/ITreasury.sol";
|
import {ITreasury} from "./interfaces/ITreasury.sol";
|
||||||
import {IDistributor} from "./interfaces/IDistributor.sol";
|
import {IDistributor} from "./interfaces/IDistributor.sol";
|
||||||
@ -78,7 +77,7 @@ contract GhostDistributor is IDistributor, GhostAccessControlled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nextRewardFor(address who) public view override returns (uint256) {
|
function nextRewardFor(address who) public view override returns (uint256) {
|
||||||
return FullMath.mulDiv(IERC20(ftso).balanceOf(who), rewardRate, DENOMINATOR);
|
return (IERC20(ftso).balanceOf(who) * rewardRate) / DENOMINATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBounty(uint256 _bounty) external override onlyGovernor {
|
function setBounty(uint256 _bounty) external override onlyGovernor {
|
||||||
@ -110,7 +109,7 @@ contract GhostDistributor is IDistributor, GhostAccessControlled {
|
|||||||
) revert NotPermissioned();
|
) revert NotPermissioned();
|
||||||
if (
|
if (
|
||||||
msg.sender == authority.guardian() &&
|
msg.sender == authority.guardian() &&
|
||||||
rate > FullMath.mulDiv(rewardRate, 25, 1_000)
|
rate > rewardRate * 25 / 1_000
|
||||||
) revert AdjustmentLimit();
|
) revert AdjustmentLimit();
|
||||||
if (!add && rate > rewardRate) revert AdjustmentUnderflow();
|
if (!add && rate > rewardRate) revert AdjustmentUnderflow();
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import {IERC20Metadata} from "@openzeppelin-contracts/token/ERC20/extensions/IER
|
|||||||
import {IUniswapV2Pair} from "@uniswap-v2-core/interfaces/IUniswapV2Pair.sol";
|
import {IUniswapV2Pair} from "@uniswap-v2-core/interfaces/IUniswapV2Pair.sol";
|
||||||
|
|
||||||
import {IBondingCalculator} from "./interfaces/IBondingCalculator.sol";
|
import {IBondingCalculator} from "./interfaces/IBondingCalculator.sol";
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
contract GhostBondingCalculator is IBondingCalculator {
|
contract GhostBondingCalculator is IBondingCalculator {
|
||||||
using FixedPoint for *;
|
using FixedPoint for *;
|
||||||
@ -26,10 +25,10 @@ contract GhostBondingCalculator is IBondingCalculator {
|
|||||||
uint256 decimals = token0 + token1 - IERC20Metadata(pair).decimals();
|
uint256 decimals = token0 + token1 - IERC20Metadata(pair).decimals();
|
||||||
|
|
||||||
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair).getReserves();
|
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair).getReserves();
|
||||||
k = FullMath.mulDiv(reserve0, reserve1, 10**decimals);
|
k = reserve0 * reserve1 / (10**decimals);
|
||||||
|
|
||||||
if (isCoefficient) {
|
if (isCoefficient) {
|
||||||
k = FullMath.mulDiv(k, 1e18, fraction);
|
k = k * 1e18 / fraction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +40,8 @@ contract GhostBondingCalculator is IBondingCalculator {
|
|||||||
uint256 totalValue = getTotalValue(pair, true);
|
uint256 totalValue = getTotalValue(pair, true);
|
||||||
uint256 totalSupply = IUniswapV2Pair(pair).totalSupply();
|
uint256 totalSupply = IUniswapV2Pair(pair).totalSupply();
|
||||||
|
|
||||||
value = FullMath.mulDiv(totalValue, FixedPoint.fraction(amount, totalSupply).decode112with18(), 1e18);
|
value = totalValue * FixedPoint.fraction(amount, totalSupply).decode112with18() / 1e18;
|
||||||
value = FullMath.mulDiv(value, fraction, 1e18);
|
value = value * fraction / 1e18;
|
||||||
}
|
}
|
||||||
|
|
||||||
function markdown(address pair) external view override returns (uint256 reserve) {
|
function markdown(address pair) external view override returns (uint256 reserve) {
|
||||||
@ -55,8 +54,8 @@ contract GhostBondingCalculator is IBondingCalculator {
|
|||||||
reserve = reserve0;
|
reserve = reserve0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reserve = FullMath.mulDiv(reserve, 2 * 1e9, getTotalValue(pair, false));
|
reserve = reserve * (2 * 1e9) / getTotalValue(pair, false);
|
||||||
reserve = FullMath.mulDiv(reserve, _sqrt(fraction), 1e9);
|
reserve = reserve * _sqrt(fraction) / 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _sqrt(uint256 a) private pure returns (uint256 c) {
|
function _sqrt(uint256 a) private pure returns (uint256 c) {
|
||||||
|
|||||||
@ -9,8 +9,6 @@ import {IGHST} from "./interfaces/IGHST.sol";
|
|||||||
import {ISTNK} from "./interfaces/ISTNK.sol";
|
import {ISTNK} from "./interfaces/ISTNK.sol";
|
||||||
import {IStaking} from "./interfaces/IStaking.sol";
|
import {IStaking} from "./interfaces/IStaking.sol";
|
||||||
|
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
contract Stinky is ISTNK, ERC20Permit {
|
contract Stinky is ISTNK, ERC20Permit {
|
||||||
uint256 private constant INITIAL_SHARES_SUPPLY = 5 * 10**15;
|
uint256 private constant INITIAL_SHARES_SUPPLY = 5 * 10**15;
|
||||||
uint256 private constant TOTAL_SHARES = type(uint256).max - (type(uint256).max % INITIAL_SHARES_SUPPLY);
|
uint256 private constant TOTAL_SHARES = type(uint256).max - (type(uint256).max % INITIAL_SHARES_SUPPLY);
|
||||||
@ -70,8 +68,8 @@ contract Stinky is ISTNK, ERC20Permit {
|
|||||||
newTotalSupply = _totalSupply;
|
newTotalSupply = _totalSupply;
|
||||||
} else {
|
} else {
|
||||||
if (currentCirculatingSupply > 0) {
|
if (currentCirculatingSupply > 0) {
|
||||||
supplyDelta = FullMath.mulDiv(supplyDelta, _totalSupply, currentCirculatingSupply);
|
supplyDelta = supplyDelta * _totalSupply / currentCirculatingSupply;
|
||||||
rebasePercent = FullMath.mulDiv(supplyDelta, 1e18, currentCirculatingSupply);
|
rebasePercent = supplyDelta * 1e18 / currentCirculatingSupply;
|
||||||
}
|
}
|
||||||
newTotalSupply = _totalSupply + supplyDelta;
|
newTotalSupply = _totalSupply + supplyDelta;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import {IUniswapV2Router01} from "@uniswap-v2-periphery-1.1.0-beta.0/interfaces/
|
|||||||
|
|
||||||
import {GhostAccessControlled} from "./types/GhostAccessControlled.sol";
|
import {GhostAccessControlled} from "./types/GhostAccessControlled.sol";
|
||||||
import {Babylonian} from "./libraries/FixedPoint.sol";
|
import {Babylonian} from "./libraries/FixedPoint.sol";
|
||||||
import {FullMath} from "./libraries/FullMath.sol";
|
|
||||||
|
|
||||||
import {IFTSO} from "./interfaces/IFTSO.sol";
|
import {IFTSO} from "./interfaces/IFTSO.sol";
|
||||||
import {ISTNK} from "./interfaces/ISTNK.sol";
|
import {ISTNK} from "./interfaces/ISTNK.sol";
|
||||||
@ -388,8 +387,8 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
|
|||||||
if (permissions[STATUS.LIQUIDITYTOKEN][token]) {
|
if (permissions[STATUS.LIQUIDITYTOKEN][token]) {
|
||||||
value = IBondingCalculator(bondCalculator[token]).valuation(token, amount);
|
value = IBondingCalculator(bondCalculator[token]).valuation(token, amount);
|
||||||
} else if (permissions[STATUS.RESERVETOKEN][token]) {
|
} else if (permissions[STATUS.RESERVETOKEN][token]) {
|
||||||
value = FullMath.mulDiv(amount, 1e9, 10**IERC20Metadata(token).decimals());
|
value = amount * 1e9 / (10**IERC20Metadata(token).decimals());
|
||||||
value = FullMath.mulDiv(value, IBondingCalculator(bondCalculator[token]).fraction(), 1e18);
|
value = value * IBondingCalculator(bondCalculator[token]).fraction() / 1e18;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,9 +53,7 @@ contract GhostWarmup is IGhostWarmup {
|
|||||||
if (msg.sender != STAKING) revert NotStakingContract();
|
if (msg.sender != STAKING) revert NotStakingContract();
|
||||||
|
|
||||||
Claim storage info = _warmupInfo[who];
|
Claim storage info = _warmupInfo[who];
|
||||||
uint256 mm = mulmod(info.deposit, payout, info.payout);
|
|
||||||
uint256 depositReduction = FullMath.mulDiv(info.deposit, payout, info.payout);
|
uint256 depositReduction = FullMath.mulDiv(info.deposit, payout, info.payout);
|
||||||
if (mm > 0) depositReduction += 1;
|
|
||||||
|
|
||||||
info.deposit -= depositReduction;
|
info.deposit -= depositReduction;
|
||||||
info.payout -= payout;
|
info.payout -= payout;
|
||||||
|
|||||||
@ -3,7 +3,6 @@ pragma solidity ^0.8.20;
|
|||||||
|
|
||||||
import {GhostAccessControlled} from "./GhostAccessControlled.sol";
|
import {GhostAccessControlled} from "./GhostAccessControlled.sol";
|
||||||
import {IGhostAuthority} from "../interfaces/IGhostAuthority.sol";
|
import {IGhostAuthority} from "../interfaces/IGhostAuthority.sol";
|
||||||
import {FullMath} from "../libraries/FullMath.sol";
|
|
||||||
import {IERC20} from "@openzeppelin-contracts/token/ERC20/IERC20.sol";
|
import {IERC20} from "@openzeppelin-contracts/token/ERC20/IERC20.sol";
|
||||||
import {SafeERC20} from "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
|
import {SafeERC20} from "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
|
|
||||||
@ -34,8 +33,8 @@ abstract contract FrontEndRewarder is GhostAccessControlled {
|
|||||||
uint256 payout,
|
uint256 payout,
|
||||||
address referral
|
address referral
|
||||||
) internal returns (uint256) {
|
) internal returns (uint256) {
|
||||||
uint256 toDao = FullMath.mulDiv(payout, daoReward, 1e4);
|
uint256 toDao = (payout * daoReward) / 1e4;
|
||||||
uint256 toRef = FullMath.mulDiv(payout, refReward, 1e4);
|
uint256 toRef = (payout * refReward) / 1e4;
|
||||||
|
|
||||||
if (whitelisted[referral]) {
|
if (whitelisted[referral]) {
|
||||||
rewards[referral] += toRef;
|
rewards[referral] += toRef;
|
||||||
|
|||||||
@ -611,62 +611,6 @@ contract StakingTest is Test {
|
|||||||
staking.ghost(receiver, ghstBalance);
|
staking.ghost(receiver, ghstBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_breakoutLogicWorks() public {
|
|
||||||
assertEq(staking.gatekeeper(), address(0));
|
|
||||||
vm.prank(GOVERNOR);
|
|
||||||
staking.setGatekeeperAddress(address(gatekeeper));
|
|
||||||
assertEq(staking.gatekeeper(), address(gatekeeper));
|
|
||||||
|
|
||||||
uint256 initialIndex = staking.index();
|
|
||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
|
||||||
uint256 rebased = _prepareAndRoll(ALICE, BIG_AMOUNT, false, false);
|
|
||||||
|
|
||||||
(uint256 deposit, uint256 payout,,) = staking.warmupInfo(ALICE);
|
|
||||||
assertEq(deposit, rebased);
|
|
||||||
assertEq(payout, ghst.balanceTo(rebased));
|
|
||||||
assertEq(staking.supplyInWarmup(), ghst.balanceFrom(payout));
|
|
||||||
|
|
||||||
vm.expectRevert();
|
|
||||||
vm.prank(BOB);
|
|
||||||
staking.breakout(receiver, payout);
|
|
||||||
|
|
||||||
|
|
||||||
uint256 requestedPayout = 1;
|
|
||||||
uint256 expectedPayout = 0;
|
|
||||||
while (expectedPayout < payout / 2) {
|
|
||||||
uint256 pseudoRandom = uint256(keccak256(abi.encodePacked("salt", requestedPayout, expectedPayout)));
|
|
||||||
uint256 range = (payout * 3) / 100;
|
|
||||||
requestedPayout = (pseudoRandom % range) + 1;
|
|
||||||
|
|
||||||
vm.expectEmit(true, true, true, false, address(gatekeeper));
|
|
||||||
emit Ghosted(receiver, requestedPayout);
|
|
||||||
|
|
||||||
vm.prank(ALICE);
|
|
||||||
staking.breakout(receiver, requestedPayout);
|
|
||||||
expectedPayout += requestedPayout;
|
|
||||||
|
|
||||||
(,uint256 tmpPayout,,) = staking.warmupInfo(ALICE);
|
|
||||||
assertEq(tmpPayout, payout - expectedPayout);
|
|
||||||
assertEq(staking.supplyInWarmup(), ghst.balanceFrom(payout - expectedPayout));
|
|
||||||
|
|
||||||
(,, uint48 end,) = staking.epoch();
|
|
||||||
skip(end);
|
|
||||||
staking.rebase();
|
|
||||||
}
|
|
||||||
|
|
||||||
(uint256 newDeposit, uint256 newPayout,,) = staking.warmupInfo(ALICE);
|
|
||||||
assertEq(newPayout, payout - expectedPayout);
|
|
||||||
assertEq(staking.supplyInWarmup(), ghst.balanceFrom(payout - expectedPayout));
|
|
||||||
assertEq(ftso.balanceOf(ALICE), 0);
|
|
||||||
|
|
||||||
vm.prank(ALICE);
|
|
||||||
staking.forfeit();
|
|
||||||
|
|
||||||
uint256 restoredPayout = expectedPayout * initialIndex / 1e18;
|
|
||||||
assertLt(ftso.balanceOf(ALICE) + restoredPayout, BIG_AMOUNT);
|
|
||||||
assertEq(newDeposit, ftso.balanceOf(ALICE));
|
|
||||||
}
|
|
||||||
|
|
||||||
function _mintAndApprove(address who, uint256 value) internal {
|
function _mintAndApprove(address who, uint256 value) internal {
|
||||||
vm.prank(VAULT);
|
vm.prank(VAULT);
|
||||||
ftso.mint(who, value);
|
ftso.mint(who, value);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user