make everyone happy about the phantomRefund with help of maturity
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
ef598ae702
commit
2623451103
@ -41,6 +41,11 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
WETH = wrapped;
|
WETH = wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addNote(address user, uint256 payout, uint48 expiry) external returns (uint256) {
|
||||||
|
if (msg.sender != TREASURY) revert NotTreasury();
|
||||||
|
return _addNote(user, payout, expiry, type(uint48).max);
|
||||||
|
}
|
||||||
|
|
||||||
function deposit(
|
function deposit(
|
||||||
uint256 id,
|
uint256 id,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
@ -77,7 +82,7 @@ contract GhostBondDepository is IBondDepository, NoteKeeper {
|
|||||||
|
|
||||||
emit Bond(id, amount, price);
|
emit Bond(id, amount, price);
|
||||||
|
|
||||||
index = addNote(user, payout, uint48(expiry), uint48(id)); // forge-lint: disable-line(unsafe-typecast)
|
index = _addNote(user, payout, uint48(expiry), uint48(id)); // forge-lint: disable-line(unsafe-typecast)
|
||||||
|
|
||||||
IWETH9(WETH).deposit{value: msg.value}();
|
IWETH9(WETH).deposit{value: msg.value}();
|
||||||
IERC20(WETH).safeTransfer(TREASURY, msg.value);
|
IERC20(WETH).safeTransfer(TREASURY, msg.value);
|
||||||
|
|||||||
@ -25,6 +25,7 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
|
|||||||
uint256 public constant EXISTENTIAL_DEPOSIT = 500 * 1e12; // 0.005
|
uint256 public constant EXISTENTIAL_DEPOSIT = 500 * 1e12; // 0.005
|
||||||
uint256 public constant FULL_GAS_RESTORATION_TIME = 3600; // 1 hour
|
uint256 public constant FULL_GAS_RESTORATION_TIME = 3600; // 1 hour
|
||||||
uint256 public constant MAX_ALLOWED_GAS_PRICE = 3e9; // 3 gwei
|
uint256 public constant MAX_ALLOWED_GAS_PRICE = 3e9; // 3 gwei
|
||||||
|
uint256 public constant PHANTOM_EXPIRY = 432000; // seconds, 5 days
|
||||||
uint256 public constant GAS_EXECUTION_BUFFER = 21000 + 5969 + 50955;
|
uint256 public constant GAS_EXECUTION_BUFFER = 21000 + 5969 + 50955;
|
||||||
uint256 public constant REGISTRY_INDEX = 0;
|
uint256 public constant REGISTRY_INDEX = 0;
|
||||||
|
|
||||||
@ -160,7 +161,7 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
|
|||||||
_lastVerificationTime = block.timestamp;
|
_lastVerificationTime = block.timestamp;
|
||||||
|
|
||||||
uint256 gasSpent = (gasStart - gasleft() + GAS_EXECUTION_BUFFER) * currentGasPrice;
|
uint256 gasSpent = (gasStart - gasleft() + GAS_EXECUTION_BUFFER) * currentGasPrice;
|
||||||
try IStaking(staking).phantomRefund(msg.sender, gasSpent, REGISTRY_INDEX) {}
|
try IStaking(staking).phantomRefund(msg.sender, gasSpent, REGISTRY_INDEX, PHANTOM_EXPIRY) {}
|
||||||
catch {
|
catch {
|
||||||
emit VoluntaryVerification(msg.sender, gasSpent);
|
emit VoluntaryVerification(msg.sender, gasSpent);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -171,14 +171,19 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
IGatekeeper(gatekeeper).ghost(receiver, amount);
|
IGatekeeper(gatekeeper).ghost(receiver, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function phantomRefund(address receiver, uint256 amount, uint256 registryIndex) external override {
|
function phantomRefund(
|
||||||
|
address receiver,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 registryIndex,
|
||||||
|
uint256 phantomExpiry
|
||||||
|
) external override {
|
||||||
if (gatekeeper != msg.sender) revert NotGatekeeper();
|
if (gatekeeper != msg.sender) revert NotGatekeeper();
|
||||||
|
|
||||||
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
|
uint48 phantomRelease = uint48(block.timestamp + phantomExpiry);
|
||||||
address treasury = ISTNK(stnk).treasury();
|
address treasury = ISTNK(stnk).treasury();
|
||||||
|
|
||||||
uint256 gasFtsoAmount = ITreasury(treasury).phantomRefund(amount, registryIndex);
|
ITreasury(treasury).phantomRefund(receiver, phantomRelease, amount, registryIndex);
|
||||||
uint256 gasGhstAmount = IGHST(ghst).balanceTo(gasFtsoAmount);
|
|
||||||
|
|
||||||
IGHST(ghst).mint(receiver, gasGhstAmount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function recall(address receiver, uint256 amount) external override {
|
function recall(address receiver, uint256 amount) external override {
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import {FullMath} from "./libraries/FullMath.sol";
|
|||||||
import {IFTSO} from "./interfaces/IFTSO.sol";
|
import {IFTSO} from "./interfaces/IFTSO.sol";
|
||||||
import {IBondingCalculator} from "./interfaces/IBondingCalculator.sol";
|
import {IBondingCalculator} from "./interfaces/IBondingCalculator.sol";
|
||||||
import {ITreasury} from "./interfaces/ITreasury.sol";
|
import {ITreasury} from "./interfaces/ITreasury.sol";
|
||||||
|
import {IBondDepository} from "./interfaces/IBondDepository.sol";
|
||||||
import {IGhostAuthority} from "./interfaces/IGhostAuthority.sol";
|
import {IGhostAuthority} from "./interfaces/IGhostAuthority.sol";
|
||||||
|
|
||||||
contract GhostTreasury is GhostAccessControlled, ITreasury {
|
contract GhostTreasury is GhostAccessControlled, ITreasury {
|
||||||
@ -25,6 +26,7 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
|
|||||||
using EnumerableSet for EnumerableSet.AddressSet;
|
using EnumerableSet for EnumerableSet.AddressSet;
|
||||||
|
|
||||||
address public immutable FTSO;
|
address public immutable FTSO;
|
||||||
|
address public bondDepository;
|
||||||
uint256 public totalReserves;
|
uint256 public totalReserves;
|
||||||
|
|
||||||
mapping(STATUS => EnumerableSet.AddressSet) private _registry;
|
mapping(STATUS => EnumerableSet.AddressSet) private _registry;
|
||||||
@ -77,20 +79,22 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function phantomRefund(
|
function phantomRefund(
|
||||||
|
address receiver,
|
||||||
|
uint48 phantomRelease,
|
||||||
uint256 gasSpent,
|
uint256 gasSpent,
|
||||||
uint256 index
|
uint256 registryIndex
|
||||||
) external override returns (uint256 gasValue) {
|
) external override returns (uint256 gasValue) {
|
||||||
if (!_permissions[STATUS.STAKING][msg.sender]) revert NotApproved();
|
if (!_permissions[STATUS.STAKING][msg.sender]) revert NotApproved();
|
||||||
|
|
||||||
address reserveToken = _registry[STATUS.RESERVETOKEN].at(index);
|
address reserveToken = _registry[STATUS.RESERVETOKEN].at(registryIndex);
|
||||||
if (!_permissions[STATUS.RESERVETOKEN][reserveToken]) revert NotApproved();
|
if (!_permissions[STATUS.RESERVETOKEN][reserveToken]) revert NotApproved();
|
||||||
|
|
||||||
uint256 totalSupply = IERC20(FTSO).totalSupply();
|
uint256 totalSupply = IERC20(FTSO).totalSupply();
|
||||||
gasValue = tokenValue(reserveToken, gasSpent);
|
gasValue = tokenValue(reserveToken, gasSpent);
|
||||||
gasValue = FullMath.mulDiv(gasValue, totalSupply, totalReserves);
|
gasValue = FullMath.mulDiv(gasValue, totalSupply, totalReserves);
|
||||||
|
|
||||||
if (gasValue <= excessReserves()) {
|
if (gasValue > 0 && gasValue <= excessReserves()) {
|
||||||
IFTSO(FTSO).mint(msg.sender, gasValue);
|
IBondDepository(bondDepository).addNote(receiver, gasValue, phantomRelease);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +182,15 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
|
|||||||
emit Permissioned(toDisable, status, false);
|
emit Permissioned(toDisable, status, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setBondDepository(address newBondDepository) external {
|
||||||
|
if (
|
||||||
|
msg.sender != authority.governor() &&
|
||||||
|
msg.sender != authority.guardian()
|
||||||
|
) revert NotApproved();
|
||||||
|
bondDepository = newBondDepository;
|
||||||
|
emit BondDepositoryUpdated(newBondDepository);
|
||||||
|
}
|
||||||
|
|
||||||
function forfeitReserves(
|
function forfeitReserves(
|
||||||
address router,
|
address router,
|
||||||
uint256 liquidity,
|
uint256 liquidity,
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
pragma solidity ^0.8.20;
|
pragma solidity ^0.8.20;
|
||||||
|
|
||||||
interface IBondDepository {
|
interface IBondDepository {
|
||||||
|
error NotTreasury();
|
||||||
error DepositoryConcluded(uint48 concludedTime);
|
error DepositoryConcluded(uint48 concludedTime);
|
||||||
error DepositoryMaxPrice(uint256 price, uint256 maxPrice);
|
error DepositoryMaxPrice(uint256 price, uint256 maxPrice);
|
||||||
error DepositoryMaxSize(uint256 payout, uint256 maxPayout);
|
error DepositoryMaxSize(uint256 payout, uint256 maxPayout);
|
||||||
@ -75,6 +76,7 @@ interface IBondDepository {
|
|||||||
) external returns (uint256 id_);
|
) external returns (uint256 id_);
|
||||||
|
|
||||||
function close(uint256 _id) external;
|
function close(uint256 _id) external;
|
||||||
|
function addNote(address user, uint256 payout, uint48 expiry) external returns (uint256);
|
||||||
function isLive(uint256 _bid) external view returns (bool);
|
function isLive(uint256 _bid) external view returns (bool);
|
||||||
function liveMarkets() external view returns (uint256[] memory);
|
function liveMarkets() external view returns (uint256[] memory);
|
||||||
function liveMarketsFor(address _quoteToken) external view returns (uint256[] memory);
|
function liveMarketsFor(address _quoteToken) external view returns (uint256[] memory);
|
||||||
|
|||||||
@ -70,7 +70,7 @@ interface IStaking {
|
|||||||
function ghost(bytes32 receiver, uint256 amount) external;
|
function ghost(bytes32 receiver, uint256 amount) external;
|
||||||
function recall(address receiver, uint256 amount) external;
|
function recall(address receiver, uint256 amount) external;
|
||||||
function recall(uint256 amount, uint256 registryIndex) external returns (address, uint256);
|
function recall(uint256 amount, uint256 registryIndex) external returns (address, uint256);
|
||||||
function phantomRefund(address receiver, uint256 amount, uint256 registryIndex) external;
|
function phantomRefund(address receiver, uint256 amount, uint256 registryIndex, uint256 phantomExpiry) external;
|
||||||
function rebase() external returns (uint256);
|
function rebase() external returns (uint256);
|
||||||
|
|
||||||
function index() external view returns (uint256);
|
function index() external view returns (uint256);
|
||||||
|
|||||||
@ -21,6 +21,7 @@ interface ITreasury {
|
|||||||
event Minted(address indexed caller, address indexed recipient, uint256 amount);
|
event Minted(address indexed caller, address indexed recipient, uint256 amount);
|
||||||
event Permissioned(address addr, STATUS indexed status, bool result);
|
event Permissioned(address addr, STATUS indexed status, bool result);
|
||||||
event Withdrawal(address indexed token, uint256 indexed amount, uint256 value);
|
event Withdrawal(address indexed token, uint256 indexed amount, uint256 value);
|
||||||
|
event BondDepositoryUpdated(address bondDepository);
|
||||||
|
|
||||||
function deposit(
|
function deposit(
|
||||||
address _token,
|
address _token,
|
||||||
@ -29,7 +30,7 @@ interface ITreasury {
|
|||||||
) external returns (uint256);
|
) external returns (uint256);
|
||||||
|
|
||||||
function registered(STATUS status, address token) external view returns(bool);
|
function registered(STATUS status, address token) external view returns(bool);
|
||||||
function phantomRefund(uint256 gasSpent, uint256 amount) external returns (uint256);
|
function phantomRefund(address receiver, uint48 phantomExpiry, uint256 gasSpent, uint256 amount) external returns (uint256);
|
||||||
function buyBack(address receiver, uint256 amount, uint256 index) external returns (address, uint256);
|
function buyBack(address receiver, uint256 amount, uint256 index) external returns (address, uint256);
|
||||||
function withdraw(address token, uint256 amount) external;
|
function withdraw(address token, uint256 amount) external;
|
||||||
function mint(address _recipient, uint256 _amount) external;
|
function mint(address _recipient, uint256 _amount) external;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ abstract contract NoteKeeper is INoteKeeper {
|
|||||||
_TREASURY = ITreasury(_treasuryAddress);
|
_TREASURY = ITreasury(_treasuryAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNote(
|
function _addNote(
|
||||||
address user,
|
address user,
|
||||||
uint256 payout,
|
uint256 payout,
|
||||||
uint48 expiry,
|
uint48 expiry,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import {Test} from "forge-std/Test.sol";
|
|||||||
import {Fatso} from "../../src/FatsoERC20.sol";
|
import {Fatso} from "../../src/FatsoERC20.sol";
|
||||||
import {Stinky} from "../../src/StinkyERC20.sol";
|
import {Stinky} from "../../src/StinkyERC20.sol";
|
||||||
import {Ghost} from "../../src/GhstERC20.sol";
|
import {Ghost} from "../../src/GhstERC20.sol";
|
||||||
|
import {GhostBondDepository} from "../../src/BondDepository.sol";
|
||||||
import {GhostAuthority} from "../../src/GhostAuthority.sol";
|
import {GhostAuthority} from "../../src/GhostAuthority.sol";
|
||||||
import {GhostTreasury} from "../../src/Treasury.sol";
|
import {GhostTreasury} from "../../src/Treasury.sol";
|
||||||
import {GhostStaking} from "../../src/Staking.sol";
|
import {GhostStaking} from "../../src/Staking.sol";
|
||||||
@ -46,6 +47,7 @@ contract GatekeeperRecallTest is Test {
|
|||||||
GhostTreasury treasury;
|
GhostTreasury treasury;
|
||||||
GhostAuthority authority;
|
GhostAuthority authority;
|
||||||
GhostBondingCalculator calculator;
|
GhostBondingCalculator calculator;
|
||||||
|
GhostBondDepository bondDepository;
|
||||||
WETH9 reserve;
|
WETH9 reserve;
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
@ -71,15 +73,25 @@ contract GatekeeperRecallTest is Test {
|
|||||||
);
|
);
|
||||||
treasury = new GhostTreasury(address(ftso), address(authority));
|
treasury = new GhostTreasury(address(ftso), address(authority));
|
||||||
calculator = new GhostBondingCalculator(address(ftso), 6000, 3);
|
calculator = new GhostBondingCalculator(address(ftso), 6000, 3);
|
||||||
|
bondDepository = new GhostBondDepository(
|
||||||
|
address(authority),
|
||||||
|
address(ftso),
|
||||||
|
address(ghst),
|
||||||
|
address(staking),
|
||||||
|
address(treasury),
|
||||||
|
address(reserve)
|
||||||
|
);
|
||||||
stnk.initialize(address(staking), address(treasury), address(ghst));
|
stnk.initialize(address(staking), address(treasury), address(ghst));
|
||||||
ghst.initialize(address(staking));
|
ghst.initialize(address(staking));
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
vm.startPrank(GOVERNOR);
|
vm.startPrank(GOVERNOR);
|
||||||
authority.pushVault(address(treasury));
|
authority.pushVault(address(treasury));
|
||||||
|
treasury.enable(ITreasury.STATUS.REWARDMANAGER, address(bondDepository), address(0));
|
||||||
treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, ALICE, address(0));
|
treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, ALICE, address(0));
|
||||||
treasury.enable(ITreasury.STATUS.RESERVETOKEN, address(reserve), address(calculator));
|
treasury.enable(ITreasury.STATUS.RESERVETOKEN, address(reserve), address(calculator));
|
||||||
treasury.enable(ITreasury.STATUS.STAKING, address(staking), address(0));
|
treasury.enable(ITreasury.STATUS.STAKING, address(staking), address(0));
|
||||||
|
treasury.setBondDepository(address(bondDepository));
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
vm.deal(ALICE, INITIAL_MINT);
|
vm.deal(ALICE, INITIAL_MINT);
|
||||||
@ -109,11 +121,11 @@ contract GatekeeperRecallTest is Test {
|
|||||||
|
|
||||||
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() * 69);
|
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() * 69);
|
||||||
|
|
||||||
uint256 bobBalanceBeforeFirst = ghst.balanceOf(BOB);
|
|
||||||
uint256 priceBeforeFirst = gatekeeper.getCurrentGasPrice();
|
uint256 priceBeforeFirst = gatekeeper.getCurrentGasPrice();
|
||||||
assertEq(priceBeforeFirst, gatekeeper.MAX_ALLOWED_GAS_PRICE());
|
assertEq(priceBeforeFirst, gatekeeper.MAX_ALLOWED_GAS_PRICE());
|
||||||
assertEq(ghst.balanceOf(BOB), 0);
|
assertEq(ghst.balanceOf(BOB), 0);
|
||||||
|
|
||||||
|
vm.txGasPrice(2 gwei);
|
||||||
vm.prank(BOB, BOB);
|
vm.prank(BOB, BOB);
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"bf06188a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000017508f1956a800000000000000000000000000000000000000000020000000000007a6980000000",
|
hex"bf06188a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000017508f1956a800000000000000000000000000000000000000000020000000000007a6980000000",
|
||||||
@ -121,10 +133,12 @@ contract GatekeeperRecallTest is Test {
|
|||||||
0x8c3fc03b5cb738777ceec396ee8647f782d6670992f8f973de2dfc83379978d5
|
0x8c3fc03b5cb738777ceec396ee8647f782d6670992f8f973de2dfc83379978d5
|
||||||
);
|
);
|
||||||
|
|
||||||
uint256 bobBalanceAfterFirst = ghst.balanceOf(BOB);
|
(uint256 pendingPayout, bool matured) = bondDepository.pendingFor(BOB, 0);
|
||||||
assertGt(bobBalanceAfterFirst, bobBalanceBeforeFirst);
|
assertGt(pendingPayout, 0); // 19273751457699280
|
||||||
|
assertFalse(matured);
|
||||||
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
||||||
|
|
||||||
|
vm.txGasPrice(2 gwei);
|
||||||
vm.prank(BOB, BOB);
|
vm.prank(BOB, BOB);
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"3137142600000000000000000000000000000000000000000000000000000000000000120000000000007a69010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000042b7ce50000000000000000000000000000000000000000000000000000000000",
|
hex"3137142600000000000000000000000000000000000000000000000000000000000000120000000000007a69010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000042b7ce50000000000000000000000000000000000000000000000000000000000",
|
||||||
@ -132,13 +146,12 @@ contract GatekeeperRecallTest is Test {
|
|||||||
0xdbeed3eb94a829710147595c1b10f2ac6ec761c9721d8cc4711842c212ac517e
|
0xdbeed3eb94a829710147595c1b10f2ac6ec761c9721d8cc4711842c212ac517e
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEq(ghst.balanceOf(BOB), bobBalanceAfterFirst);
|
|
||||||
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
||||||
|
|
||||||
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() / 2);
|
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() / 2);
|
||||||
uint256 gasPriceRestored = gatekeeper.getCurrentGasPrice();
|
uint256 gasPriceRestored = gatekeeper.getCurrentGasPrice();
|
||||||
assertEq(gasPriceRestored, gatekeeper.MAX_ALLOWED_GAS_PRICE() / 2);
|
assertEq(gasPriceRestored, gatekeeper.MAX_ALLOWED_GAS_PRICE() / 2);
|
||||||
|
|
||||||
|
vm.txGasPrice(2 gwei);
|
||||||
vm.prank(BOB, BOB);
|
vm.prank(BOB, BOB);
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"31371426000000000000000000000000000000000000000000000000000000000000000d0000000000007a6901010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064e4e33ef800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000",
|
hex"31371426000000000000000000000000000000000000000000000000000000000000000d0000000000007a6901010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064e4e33ef800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000",
|
||||||
@ -146,8 +159,13 @@ contract GatekeeperRecallTest is Test {
|
|||||||
0xc2da93948f869c5102992bd1cbd70ef5f821ff522305c69d113faf2e89570ce7
|
0xc2da93948f869c5102992bd1cbd70ef5f821ff522305c69d113faf2e89570ce7
|
||||||
);
|
);
|
||||||
|
|
||||||
assertGt(ghst.balanceOf(BOB), bobBalanceAfterFirst);
|
(pendingPayout, matured) = bondDepository.pendingFor(BOB, 1);
|
||||||
|
assertGt(pendingPayout, 69);
|
||||||
|
assertFalse(matured);
|
||||||
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
assertEq(gatekeeper.getCurrentGasPrice(), 0);
|
||||||
|
|
||||||
|
uint256[] memory indexes = bondDepository.indexesFor(BOB);
|
||||||
|
assertEq(indexes.length, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_recallChainWorks() public {
|
function test_recallChainWorks() public {
|
||||||
@ -168,7 +186,6 @@ contract GatekeeperRecallTest is Test {
|
|||||||
uint256 actualAmount = 105000000000000000;
|
uint256 actualAmount = 105000000000000000;
|
||||||
address actualReceiver = address(0x0000000000000000000000000000000000000002);
|
address actualReceiver = address(0x0000000000000000000000000000000000000002);
|
||||||
|
|
||||||
uint256 bobGhstBefore = ghst.balanceOf(BOB);
|
|
||||||
uint256 receiverEthBefore = actualReceiver.balance;
|
uint256 receiverEthBefore = actualReceiver.balance;
|
||||||
uint256 receiverGhstBefore = ghst.balanceOf(actualReceiver);
|
uint256 receiverGhstBefore = ghst.balanceOf(actualReceiver);
|
||||||
uint256 totalReservesBefore = treasury.totalReserves();
|
uint256 totalReservesBefore = treasury.totalReserves();
|
||||||
@ -185,14 +202,15 @@ contract GatekeeperRecallTest is Test {
|
|||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
{
|
{
|
||||||
uint256 bobGhstAfter = ghst.balanceOf(BOB);
|
(uint256 bobPhantomClaimAfter, bool maturedAfter) = bondDepository.pendingFor(BOB, 0);
|
||||||
uint256 receiverGhstAfter = ghst.balanceOf(actualReceiver);
|
uint256 receiverGhstAfter = ghst.balanceOf(actualReceiver);
|
||||||
|
|
||||||
|
assertFalse(maturedAfter);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
ghst.balanceFrom(bobGhstAfter - bobGhstBefore) * totalReservesBefore / totalSupplyBefore
|
ghst.balanceFrom(bobPhantomClaimAfter) * totalReservesBefore / totalSupplyBefore
|
||||||
> gatekeeper.GAS_EXECUTION_BUFFER()
|
> gatekeeper.GAS_EXECUTION_BUFFER()
|
||||||
);
|
);
|
||||||
assertTrue(bobGhstAfter > bobGhstBefore);
|
|
||||||
assertApproxEqAbs(receiverGhstAfter - receiverGhstBefore, actualAmount / 2, 1e18);
|
assertApproxEqAbs(receiverGhstAfter - receiverGhstBefore, actualAmount / 2, 1e18);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +229,8 @@ contract GatekeeperRecallTest is Test {
|
|||||||
uint256 backingRatioBefore = totalReservesBefore * 1e18 / totalSupplyBefore;
|
uint256 backingRatioBefore = totalReservesBefore * 1e18 / totalSupplyBefore;
|
||||||
uint256 backingRatioAfter = treasury.totalReserves() * 1e18 / ftso.totalSupply();
|
uint256 backingRatioAfter = treasury.totalReserves() * 1e18 / ftso.totalSupply();
|
||||||
|
|
||||||
uint256 gasFtsoMinted = ghst.balanceFrom(ghst.balanceOf(BOB) - bobGhstBefore);
|
(uint256 bobPhantomClaim,) = bondDepository.pendingFor(BOB, 0);
|
||||||
|
uint256 gasFtsoMinted = ghst.balanceFrom(bobPhantomClaim);
|
||||||
uint256 expectedDelta = (backingRatioBefore * gasFtsoMinted) / totalSupplyBefore;
|
uint256 expectedDelta = (backingRatioBefore * gasFtsoMinted) / totalSupplyBefore;
|
||||||
|
|
||||||
assertApproxEqAbs(backingRatioAfter, backingRatioBefore - expectedDelta, 1000);
|
assertApproxEqAbs(backingRatioAfter, backingRatioBefore - expectedDelta, 1000);
|
||||||
@ -220,5 +239,22 @@ contract GatekeeperRecallTest is Test {
|
|||||||
treasury.auditReserves();
|
treasury.auditReserves();
|
||||||
assertApproxEqAbs(treasury.totalReserves() * 1e18 / ftso.totalSupply(), backingRatioBefore - expectedDelta, 2000);
|
assertApproxEqAbs(treasury.totalReserves() * 1e18 / ftso.totalSupply(), backingRatioBefore - expectedDelta, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
(uint256 phantomClaim, bool claimMatured) = bondDepository.pendingFor(BOB, 0);
|
||||||
|
assertFalse(claimMatured);
|
||||||
|
|
||||||
|
vm.expectRevert();
|
||||||
|
bondDepository.redeemAll(BOB, true);
|
||||||
|
|
||||||
|
vm.warp(block.timestamp + gatekeeper.PHANTOM_EXPIRY() + 69);
|
||||||
|
(phantomClaim, claimMatured) = bondDepository.pendingFor(BOB, 0);
|
||||||
|
assertTrue(claimMatured);
|
||||||
|
|
||||||
|
vm.prank(BOB);
|
||||||
|
uint256 actualPayout = bondDepository.redeemAll(BOB, true);
|
||||||
|
assertEq(phantomClaim, actualPayout);
|
||||||
|
assertEq(actualPayout, ghst.balanceOf(BOB));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user