diff --git a/.env.template b/.env.template index 799d8f0..d136915 100644 --- a/.env.template +++ b/.env.template @@ -69,9 +69,6 @@ INITIAL_INDEX= COEFFICIENT_NUMERATOR= COEFFICIENT_DENOMINATOR= -## Blocks needed for permissions to take place, only needed if timelock enabled -BLOCKS_NEEDED_FOR_TREASURY_QUEUE= - ## Multiplier for each native coin where result of multiplication represents amount ## of mint tokens. RESERVE_MINT_RATE= @@ -105,10 +102,8 @@ GOVERNOR_PROPOSAL_THRESHOLD= GOVERNOR_QUORUM_FRACTION= ###################### Initial ghosted supply on gatekeeper ########################### -## existential - minimum amount that could be reflected inside other chain ## ## previousWeaver - previous weaver address if any to make linked list of weavers ## ####################################################################################### -INITIAL_EXISTENTIAL_DEPOSIT= PREVIOUS_WEAVER_ADDRESS= SEPOLIA_TEST_RPC_URL= diff --git a/src/Gatekeeper.sol b/src/Gatekeeper.sol index 7598bc4..c14bfa3 100644 --- a/src/Gatekeeper.sol +++ b/src/Gatekeeper.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +import {IWETH9} from "./interfaces/IWETH9.sol"; import {IStaking} from "./interfaces/IStaking.sol"; import {IGatekeeper} from "./interfaces/IGatekeeper.sol"; import {IStorageHistory} from "./interfaces/IStorageHistory.sol"; @@ -24,10 +25,13 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard { uint256 private constant SECP256K1_Q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; uint256 private constant SHIFT_FACTOR = (2**128) % SECP256K1_N; + uint256 public constant GAS_RECALL_SPENDING = 329188; + uint256 public constant EXISTENTIAL_DEPOSIT = 500 * 1e12; + uint256 public constant REGISTRY_INDEX = 0; + address public override staking; address public override deployer; address public override storageHistory; - uint256 public override existentialDeposit; address private _previousAddress; bool private _initialized; @@ -35,16 +39,14 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard { Checkpoints.Trace256 private _aggregatedPublicKeys; mapping(bytes32 => uint256) private _packedRotationStates; - constructor( - uint256 _existentialDeposit, - address _storageHistory - ) { - existentialDeposit = _existentialDeposit; + constructor(address _storageHistory) { storageHistory = _storageHistory; staking = msg.sender; deployer = tx.origin; } + receive() external payable {} + function initialize(address _previousGatekeeperAddress) external override { if (_previousGatekeeperAddress != address(0)) { require(_initialized == false); @@ -124,7 +126,7 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard { function ghost(bytes32 receiver, uint256 amount) external override returns (uint256) { if (msg.sender != staking) revert NotStaking(); - if (amount < existentialDeposit) revert NonExistentAmount(); + if (amount < EXISTENTIAL_DEPOSIT) revert NonExistentAmount(); IStorageHistory(storageHistory).increaseBridgeIn(amount); @@ -143,25 +145,25 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard { if (payload.chainId != block.chainid) revert WrongChainId(); StorageHistory(storageHistory).trySetTransactionExecuted(exodusSession); - IStorageHistory(storageHistory).tryIncreaseBridgeOut(amount); - uint256 bountyAmount = FullMath.mulDiv(amount, uint256(payload.bounty), BOUNTY_DIVISOR); + uint256 bountyAmount = FullMath.mulDiv(amount, BOUNTY_DIVISOR - uint256(payload.bounty), BOUNTY_DIVISOR); uint256 receiverAmount = amount - bountyAmount; + uint256 bridgeOutImbalance = receiverAmount; IStaking(staking).recall(payload.receiver, receiverAmount); if (bountyAmount > 0) { - uint256 totalReserves = IStaking(staking).totalReserves(); - uint256 baseSupply = IStaking(staking).baseSupply(); - uint256 minimumNativeRequired = FullMath.mulDiv(bountyAmount, totalReserves, baseSupply); + uint256 gasSpent = GAS_RECALL_SPENDING * tx.gasprice; + (address token, uint256 forGas, uint256 sent) = IStaking(staking).recall(bountyAmount, gasSpent, REGISTRY_INDEX); + bridgeOutImbalance += forGas; - if (minimumNativeRequired > msg.value) revert InsufficientValue(); - IStaking(staking).recall(tx.origin, bountyAmount); - - (bool sentSuccess,) = payload.receiver.call{ value: msg.value }(""); + IWETH9(token).withdraw(sent); + (bool sentSuccess,) = payload.receiver.call{ value: sent }(""); if (!sentSuccess) revert SendFailed(); } + IStorageHistory(storageHistory).tryIncreaseBridgeOut(bridgeOutImbalance); + emit Recalled(payload.receiver, amount); } diff --git a/src/Staking.sol b/src/Staking.sol index c37e8f6..ee01321 100644 --- a/src/Staking.sol +++ b/src/Staking.sol @@ -9,6 +9,7 @@ import {Gatekeeper} from "./Gatekeeper.sol"; import {StorageHistory} from "./types/StorageHistory.sol"; import {GhostAccessControlled} from "./types/GhostAccessControlled.sol"; +import {IFTSO} from "./interfaces/IFTSO.sol"; import {ISTNK} from "./interfaces/ISTNK.sol"; import {IGHST} from "./interfaces/IGHST.sol"; import {IStaking} from "./interfaces/IStaking.sol"; @@ -46,8 +47,7 @@ contract GhostStaking is IStaking, GhostAccessControlled { uint48 _epochLength, uint48 _firstEpochNumber, uint48 _firstEpochTime, - address _authority, - uint256 _existentialDeposit + address _authority ) GhostAccessControlled(IGhostAuthority(_authority)) { ftso = _ftso; stnk = _stnk; @@ -62,7 +62,7 @@ contract GhostStaking is IStaking, GhostAccessControlled { GhostWarmup newWarmup = new GhostWarmup(_ghst); StorageHistory newHistory = new StorageHistory(); - Gatekeeper newGatekeeper = new Gatekeeper(_existentialDeposit, address(newHistory)); + Gatekeeper newGatekeeper = new Gatekeeper(address(newHistory)); IStorageHistory(newHistory).setOwner(address(newGatekeeper)); IGatekeeper(newGatekeeper).initialize(address(0)); @@ -172,6 +172,29 @@ contract GhostStaking is IStaking, GhostAccessControlled { IGHST(ghst).mint(receiver, amount); } + function recall( + uint256 amount, + uint256 gasSpent, + uint256 registryIndex + ) external override returns (address reserveToken, uint256 gasGhstAmount, uint256 value) { + if (gatekeeper != msg.sender) revert NotGatekeeper(); + + address treasury = ISTNK(stnk).treasury(); + uint256 ftsoAmount = IGHST(ghst).balanceFrom(amount); + + uint256 gasFtsoAmount; + (reserveToken, value, gasFtsoAmount) = ITreasury(treasury).buyBack( + msg.sender, + ftsoAmount, + gasSpent, + registryIndex + ); + + gasGhstAmount = IGHST(ghst).balanceTo(gasFtsoAmount); + IFTSO(ftso).burn(ftsoAmount - gasFtsoAmount); + IGHST(ghst).mint(tx.origin, gasGhstAmount); + } + function rebase() public override returns (uint256 bounty) { if (epoch.end <= block.timestamp && block.number > _lastRebaseBlock) { ISTNK(stnk).rebase(epoch.distribute, epoch.number); diff --git a/src/Treasury.sol b/src/Treasury.sol index e774516..47211c7 100644 --- a/src/Treasury.sol +++ b/src/Treasury.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin-contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "@openzeppelin-contracts/utils/structs/EnumerableSet.sol"; import {IUniswapV2Factory} from "@uniswap-v2-core-1.0.1/interfaces/IUniswapV2Factory.sol"; import {IUniswapV2Pair} from "@uniswap-v2-core-1.0.1/interfaces/IUniswapV2Pair.sol"; @@ -21,25 +22,22 @@ import {IGhostAuthority} from "./interfaces/IGhostAuthority.sol"; contract GhostTreasury is GhostAccessControlled, ITreasury { using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.AddressSet; - address public immutable ftso; // forge-lint: disable-line(screaming-snake-case-immutable) - uint256 public immutable blocksNeededForQueue; // forge-lint: disable-line(screaming-snake-case-immutable) + address public immutable FTSO; uint256 public totalReserves; uint256 public totalDebt; - uint256 public ftsoDebt; - mapping(STATUS => address[]) public registry; - mapping(STATUS => mapping(address => bool)) public permissions; + mapping(STATUS => EnumerableSet.AddressSet) private _registry; + mapping(STATUS => mapping(address => bool)) private _permissions; mapping(address => address) public bondCalculator; constructor( address _ftso, - uint256 _timelock, address _authority ) GhostAccessControlled(IGhostAuthority(_authority)) { - ftso = _ftso; - blocksNeededForQueue = _timelock; + FTSO = _ftso; } function deposit( @@ -47,30 +45,30 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { uint256 amount, uint256 profit ) external override returns (uint256 send) { - if (permissions[STATUS.RESERVETOKEN][token]) { - if (!permissions[STATUS.RESERVEDEPOSITOR][msg.sender]) revert NotApproved(); - } else if (permissions[STATUS.LIQUIDITYTOKEN][token]) { - if (!permissions[STATUS.LIQUIDITYDEPOSITOR][msg.sender]) revert NotApproved(); + if (_permissions[STATUS.RESERVETOKEN][token]) { + if (!_permissions[STATUS.RESERVEDEPOSITOR][msg.sender]) revert NotApproved(); + } else if (_permissions[STATUS.LIQUIDITYTOKEN][token]) { + if (!_permissions[STATUS.LIQUIDITYDEPOSITOR][msg.sender]) revert NotApproved(); } else revert InvalidToken(); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); uint256 value = tokenValue(token, amount); send = value - profit; - IFTSO(ftso).mint(msg.sender, send); + IFTSO(FTSO).mint(msg.sender, send); totalReserves = totalReserves + value; emit Deposit(token, amount, value); } function mint(address recipient, uint256 amount) external override { - if (!permissions[STATUS.REWARDMANAGER][msg.sender]) revert NotApproved(); + if (!_permissions[STATUS.REWARDMANAGER][msg.sender]) revert NotApproved(); if (amount > excessReserves()) revert InsufficientReserves(); - IFTSO(ftso).mint(recipient, amount); + IFTSO(FTSO).mint(recipient, amount); emit Minted(msg.sender, recipient, amount); } function withdraw(address token, uint256 amount) external onlyGovernor override { - if (!permissions[STATUS.RESERVETOKEN][token]) revert NotAccepted(); + if (!_permissions[STATUS.RESERVETOKEN][token]) revert NotAccepted(); uint256 value = tokenValue(token, amount); totalReserves = totalReserves - value; @@ -79,6 +77,30 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { emit Withdrawal(token, amount, value); } + function buyBack( + address receiver, + uint256 amount, + uint256 gasSpent, + uint256 index + ) external override returns (address reserveToken, uint256 value, uint256 gasValue) { + if (!_permissions[STATUS.STAKING][msg.sender]) revert NotApproved(); + + reserveToken = _registry[STATUS.RESERVETOKEN].at(index); + if (!_permissions[STATUS.RESERVETOKEN][reserveToken]) revert NotApproved(); + + uint256 totalSupply = IERC20(FTSO).totalSupply(); + gasValue = tokenValue(reserveToken, gasSpent); + gasValue = FullMath.mulDiv(gasValue, totalSupply, totalReserves); + if (amount <= gasValue) revert GasExceedsBounty(); + + uint256 reservesToSend = FullMath.mulDiv(amount - gasValue, totalReserves, totalSupply); + totalReserves = totalReserves - reservesToSend; + + value = FullMath.mulDiv(reservesToSend, 1e18, IBondingCalculator(bondCalculator[reserveToken]).fraction()); + value = FullMath.mulDiv(value, 10**IERC20Metadata(reserveToken).decimals(), 1e9); + IERC20(reserveToken).safeTransfer(receiver, value); + } + function auditReserves() external { if ( msg.sender != authority.governor() && @@ -86,12 +108,12 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { ) revert NotApproved(); uint256 reserves; - address[] memory reserveTokens = registry[STATUS.RESERVETOKEN]; + uint256 reserveTokensLength = _registry[STATUS.RESERVETOKEN].length(); uint256 i; - for (; i < reserveTokens.length;) { - address reserveToken = reserveTokens[i]; - if (permissions[STATUS.RESERVETOKEN][reserveToken]) { + for (; i < reserveTokensLength;) { + address reserveToken = _registry[STATUS.RESERVETOKEN].at(i); + if (_permissions[STATUS.RESERVETOKEN][reserveToken]) { reserves = reserves + tokenValue( reserveToken, IERC20(reserveToken).balanceOf(address(this)) @@ -100,11 +122,12 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { unchecked { ++i; } } - address[] memory liquidityTokens = registry[STATUS.LIQUIDITYTOKEN]; + uint256 liquidityTokensLength = _registry[STATUS.LIQUIDITYTOKEN].length(); + i = 0; - for (; i < liquidityTokens.length;) { - address liquidityToken = liquidityTokens[i]; - if (permissions[STATUS.LIQUIDITYTOKEN][liquidityToken]) { + for (; i < liquidityTokensLength;) { + address liquidityToken = _registry[STATUS.LIQUIDITYTOKEN].at(i); + if (_permissions[STATUS.LIQUIDITYTOKEN][liquidityToken]) { reserves = reserves + tokenValue( liquidityToken, IERC20(liquidityToken).balanceOf(address(this)) @@ -122,11 +145,13 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { address someAddress, address calculatorAddress ) external onlyGovernor { - permissions[status][someAddress] = true; - (bool registered, ) = indexInRegistry(someAddress, status); - if (!registered && (status == STATUS.LIQUIDITYTOKEN || status == STATUS.RESERVETOKEN)) { - assert(calculatorAddress != address(0)); - registry[status].push(someAddress); + _permissions[status][someAddress] = true; + + bool alreadyRegistered = _registry[status].contains(someAddress); + if (!alreadyRegistered && (status == STATUS.LIQUIDITYTOKEN || status == STATUS.RESERVETOKEN)) { + if (calculatorAddress == address(0)) revert(); + + _registry[status].add(someAddress); bondCalculator[someAddress] = calculatorAddress; } emit Permissioned(someAddress, status, true); @@ -137,7 +162,7 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { msg.sender != authority.governor() && msg.sender != authority.guardian() ) revert NotApproved(); - permissions[status][toDisable] = false; + _permissions[status][toDisable] = false; emit Permissioned(toDisable, status, false); } @@ -147,7 +172,7 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { bool destroyerMode ) external onlyGovernor { address weth = IUniswapV2Router01(router).WETH(); - address pair = IUniswapV2Factory(IUniswapV2Router01(router).factory()).getPair(ftso, weth); + address pair = IUniswapV2Factory(IUniswapV2Router01(router).factory()).getPair(FTSO, weth); IERC20(pair).safeTransfer(pair, liquidity); (uint256 amount0, uint256 amount1) = IUniswapV2Pair(pair).burn(address(this)); @@ -157,15 +182,15 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { address token0 = IUniswapV2Pair(pair).token0(); address token1 = IUniswapV2Pair(pair).token1(); - if (token0 == ftso) { + if (token0 == FTSO) { amountToDestroy = amount0; } - if (token1 == ftso) { + if (token1 == FTSO) { amountToDestroy = amount1; } - IFTSO(ftso).burn(amountToDestroy); + IFTSO(FTSO).burn(amountToDestroy); } } @@ -174,16 +199,16 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { uint256 amount ) external onlyGovernor { address weth = IUniswapV2Router01(router).WETH(); - address pair = IUniswapV2Factory(IUniswapV2Router01(router).factory()).getPair(ftso, weth); + address pair = IUniswapV2Factory(IUniswapV2Router01(router).factory()).getPair(FTSO, weth); IERC20(weth).approve(router, amount); (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pair).getReserves(); address[] memory path = new address[](2); path[0] = weth; - path[1] = ftso; + path[1] = FTSO; - if (ftso < weth) { + if (FTSO < weth) { reserve0 = reserve1 ^ reserve0; reserve1 = reserve1 ^ reserve0; reserve0 = reserve1 ^ reserve0; @@ -202,48 +227,41 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { amountIn = amount - amountIn; IERC20(weth).safeTransfer(pair, amountIn); - IERC20(ftso).safeTransfer(pair, amounts[1]); + IERC20(FTSO).safeTransfer(pair, amounts[1]); IUniswapV2Pair(pair).mint(address(this)); } - function indexInRegistry( - address someAddress, - STATUS status - ) public view override returns (bool, uint256) { - address[] memory entries = registry[status]; - uint256 i; - for (; i < entries.length; ) { - if (someAddress == entries[i]) { - return (true, i); - } - unchecked { ++i; } - } - return (false, 0); + function permissioned(STATUS status, address someAddress) external view returns (bool) { + return _permissions[status][someAddress]; + } + + function registered(STATUS status, address someAddress) external view returns (bool) { + return _registry[status].contains(someAddress); } function originalCoefficient() external view returns (uint256) { - address[] memory reserveTokens = registry[STATUS.RESERVETOKEN]; - return IBondingCalculator(bondCalculator[reserveTokens[0]]).fraction(); + address reserveToken = _registry[STATUS.RESERVETOKEN].at(0); + return IBondingCalculator(bondCalculator[reserveToken]).fraction(); } function excessReserves() public view override returns (uint256) { - return totalReserves - (IFTSO(ftso).totalSupply() - totalDebt); + return totalReserves - (IFTSO(FTSO).totalSupply() - totalDebt); } function tokenValue( address token, uint256 amount ) public view override returns (uint256 value) { - if (permissions[STATUS.LIQUIDITYTOKEN][token]) { + if (_permissions[STATUS.LIQUIDITYTOKEN][token]) { 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 = FullMath.mulDiv(value, IBondingCalculator(bondCalculator[token]).fraction(), 1e18); } } function baseSupply() external view override returns (uint256) { - return IFTSO(ftso).totalSupply() - ftsoDebt; + return IFTSO(FTSO).totalSupply(); } function _quantityToBeSwapped(uint256 xa, uint256 x1) internal pure returns (uint256) { diff --git a/src/interfaces/IGatekeeper.sol b/src/interfaces/IGatekeeper.sol index c48e030..1472c46 100644 --- a/src/interfaces/IGatekeeper.sol +++ b/src/interfaces/IGatekeeper.sol @@ -21,7 +21,6 @@ interface IGatekeeper { function deployer() external view returns (address); function ghostedSupply() external view returns (uint256); function storageHistory() external view returns (address); - function existentialDeposit() external view returns (uint256); function latestPublicKeyInfo() external view returns (bytes32, uint8, uint64); function getRotationInfoAt(uint256 session) external view returns (bytes32, uint8, uint64); diff --git a/src/interfaces/IStaking.sol b/src/interfaces/IStaking.sol index 83d31e7..43b0df7 100644 --- a/src/interfaces/IStaking.sol +++ b/src/interfaces/IStaking.sol @@ -69,6 +69,7 @@ interface IStaking { function unwrap(address _to, uint256 _amount) external returns (uint256 sBalance_); function ghost(bytes32 receiver, uint256 amount) external; function recall(address receiver, uint256 amount) external; + function recall(uint256 amount, uint256 gasSpent, uint256 registryIndex) external returns (address, uint256, uint256); function rebase() external returns (uint256); function index() external view returns (uint256); diff --git a/src/interfaces/ITreasury.sol b/src/interfaces/ITreasury.sol index fe795e0..4092ec8 100644 --- a/src/interfaces/ITreasury.sol +++ b/src/interfaces/ITreasury.sol @@ -5,6 +5,7 @@ interface ITreasury { error NotApproved(); error NotAccepted(); error InvalidToken(); + error GasExceedsBounty(); error InsufficientReserves(); enum STATUS { @@ -12,7 +13,8 @@ interface ITreasury { RESERVETOKEN, LIQUIDITYDEPOSITOR, LIQUIDITYTOKEN, - REWARDMANAGER + REWARDMANAGER, + STAKING } event Deposit(address indexed token, uint256 amount, uint256 value); @@ -27,10 +29,10 @@ interface ITreasury { uint256 _profit ) external returns (uint256); + function buyBack(address receiver, uint256 amount, uint256 gasSpent, uint256 index) external returns (address, uint256, uint256); function withdraw(address token, uint256 amount) external; function mint(address _recipient, uint256 _amount) external; function tokenValue(address _token, uint256 _amount) external view returns (uint256 value_); - function indexInRegistry(address _address, STATUS _status) external view returns (bool, uint256); function excessReserves() external view returns (uint256); function baseSupply() external view returns (uint256); function totalReserves() external view returns (uint256); diff --git a/test/bonding/BondDepositorty.t.sol b/test/bonding/BondDepositorty.t.sol index 5f28eed..79b0bf3 100644 --- a/test/bonding/BondDepositorty.t.sol +++ b/test/bonding/BondDepositorty.t.sol @@ -75,10 +75,9 @@ contract GhostBondDepositoryTest is Test { EPOCH_LENGTH, EPOCH_NUMBER, EPOCH_END_TIME, - address(authority), - 0 + address(authority) ); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); calculator = new GhostBondingCalculator(address(ftso), 1, 1); stnk.initialize(address(staking), address(treasury), address(ghst)); ghst.initialize(address(staking)); diff --git a/test/gatekeeper/Gatekeeper.t.sol b/test/gatekeeper/Gatekeeper.t.sol index d14e8ad..81fa0c3 100644 --- a/test/gatekeeper/Gatekeeper.t.sol +++ b/test/gatekeeper/Gatekeeper.t.sol @@ -7,6 +7,7 @@ import {FullMath} from "../../src/libraries/FullMath.sol"; import {RequestPacking} from "../../src/libraries/Packing.sol"; import {IStorageHistory} from "../../src/interfaces/IStorageHistory.sol"; import {StorageHistory} from "../../src/types/StorageHistory.sol"; +import {WETH9} from "../../src/mocks/WETH9.sol"; contract MockGovernance is Test { address public immutable GATEKEEPER; @@ -137,12 +138,14 @@ contract MockGovernance is Test { contract MockStaking is Test { Gatekeeper public gatekeeper; + WETH9 public mockReserve; mapping(address => uint256) private _recalledAmounts; - constructor(uint256 existential) { + constructor() { + mockReserve = new WETH9(); StorageHistory history = new StorageHistory(); - gatekeeper = new Gatekeeper(existential, address(history)); + gatekeeper = new Gatekeeper(address(history)); gatekeeper.initialize(address(0)); history.setOwner(address(gatekeeper)); } @@ -169,6 +172,11 @@ contract MockStaking is Test { _recalledAmounts[receiver] += amount; } + function recall(uint256 amount, uint256, uint256) external returns (address, uint256, uint256){ + _recalledAmounts[tx.origin] += amount; + return (address(mockReserve), 0, 0); + } + function recalledAmount(address who) external view returns (uint256) { return _recalledAmounts[who]; } @@ -187,7 +195,6 @@ contract GatekeeperTest is Test { address constant ALICE = 0x0000000000000000000000000000000000000001; address constant BOB = 0x0000000000000000000000000000000000000002; - uint256 constant EXISTENTIAL = 1337; uint256 constant INIT_AMOUNT = 69 * 1e18; address constant DUMMY_ADDRESS = address(0x0101010101010101010101010101010101010101); @@ -199,7 +206,7 @@ contract GatekeeperTest is Test { function setUp() public { vm.prank(ALICE, ALICE); - staking = new MockStaking(EXISTENTIAL); + staking = new MockStaking(); gatekeeper = staking.gatekeeper(); MockGovernance tempGov = new MockGovernance(address(gatekeeper), DUMMY_ADDRESS); @@ -215,7 +222,7 @@ contract GatekeeperTest is Test { } function test_ghostTokensWork(uint256 ghostAmount) public { - vm.assume(ghostAmount >= EXISTENTIAL && ghostAmount < type(uint96).max); + vm.assume(ghostAmount >= gatekeeper.EXISTENTIAL_DEPOSIT() && ghostAmount < type(uint96).max); bytes32 receiver = bytes32(abi.encodePacked(ALICE)); uint256 ghostedSupply = gatekeeper.ghostedSupply(); @@ -235,7 +242,7 @@ contract GatekeeperTest is Test { } function test_ghostTokensEmitsEvent(uint256 ghostAmount) public { - vm.assume(ghostAmount >= EXISTENTIAL); + vm.assume(ghostAmount >= gatekeeper.EXISTENTIAL_DEPOSIT()); bytes32 receiver = bytes32(abi.encodePacked(ALICE)); vm.expectEmit(true, true, true, false, address(gatekeeper)); @@ -245,7 +252,7 @@ contract GatekeeperTest is Test { } function test_recallWork(uint256 exodusSession, uint256 bobAmount, uint32 bobCommission) public { - vm.assume(bobAmount > 1337 && bobAmount < 1_000 ether); + vm.assume(bobAmount > gatekeeper.EXISTENTIAL_DEPOSIT() && bobAmount < 1_000 ether); vm.assume(bobCommission > 0 && bobCommission <= type(uint32).max); address storageHistory = gatekeeper.storageHistory(); @@ -259,19 +266,9 @@ contract GatekeeperTest is Test { vm.deal(ALICE, nativeNeeded + 1 ether); assertEq(BOB.balance, 0 ether); - uint256 aliceStartingNative = ALICE.balance; - - uint256 previousAliceAmount = staking.recalledAmount(ALICE); - uint256 previousBobAmount = staking.recalledAmount(BOB); vm.prank(ALICE); - staking.runRecall{value: nativeNeeded}(exodusSession, bobAmount, bobPacked, ALICE); - - assertApproxEqAbs(previousAliceAmount + commissionAmount, staking.recalledAmount(ALICE), 1000); - assertApproxEqAbs(previousBobAmount + (bobAmount - commissionAmount), staking.recalledAmount(BOB), 1000); - - assertEq(BOB.balance, nativeNeeded); - assertEq(ALICE.balance, aliceStartingNative - nativeNeeded); + staking.runRecall(exodusSession, bobAmount, bobPacked, ALICE); assert(IStorageHistory(storageHistory).isTransactionExecuted(exodusSession)); } @@ -283,7 +280,7 @@ contract GatekeeperTest is Test { } function test_couldNotBridgeBelowExistential(uint256 amount) public { - vm.assume(amount < EXISTENTIAL); + vm.assume(amount < gatekeeper.EXISTENTIAL_DEPOSIT()); bytes32 receiver = bytes32(abi.encodePacked(ALICE)); vm.expectRevert(); @@ -363,6 +360,7 @@ contract GatekeeperTest is Test { // execute bridge out, happened on DKG #0 // amount: 69; commission: 0%; ALICE // exodus session #1 + vm.prank(ALICE, ALICE); gatekeeper.verify( hex"bf06188a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000010000000000007a6900000000", hex"04bccb4cd4633e2c61ca5c65006a6a09baa893be219b21509866123a8d6299f92aefe9c380bd9728dbe0b93a8042f431636d08ed191b5c04062bf14e1347059cb9", @@ -393,10 +391,8 @@ contract GatekeeperTest is Test { 0x772731b359ee7ecac7830438333e4ffb61759b36610f69cef20f66f7a79a405f ); - assertEq(aliceAmountBefore + 210, staking.recalledAmount(ALICE)); - assertEq(bobAmountBefore + 210, staking.recalledAmount(BOB)); - assertEq(aliceBalanceBefore - buyback, ALICE.balance); - assertEq(bobBalanceBefore + buyback, BOB.balance); + assertApproxEqAbs(aliceAmountBefore + 210, staking.recalledAmount(ALICE), 1); + assertApproxEqAbs(bobAmountBefore + 210, staking.recalledAmount(BOB), 1); // execute setDistributor, exodusSession: 2 vm.prank(ALICE); diff --git a/test/gatekeeper/GatekeeperHistory.t.sol b/test/gatekeeper/GatekeeperHistory.t.sol index 0d0e2af..c1c1172 100644 --- a/test/gatekeeper/GatekeeperHistory.t.sol +++ b/test/gatekeeper/GatekeeperHistory.t.sol @@ -7,21 +7,24 @@ import {IStorageHistory} from "../../src/interfaces/IStorageHistory.sol"; import {IGatekeeper} from "../../src/interfaces/IGatekeeper.sol"; import {RequestPacking} from "../../src/libraries/Packing.sol"; import {StorageHistory} from "../../src/types/StorageHistory.sol"; +import {WETH9} from "../../src/mocks/WETH9.sol"; contract MockStaking is Test { Gatekeeper public gatekeeper; + WETH9 public mockReserve; mapping(address => uint256) private _recalledAmounts; - constructor(uint256 existential) { + constructor() { + mockReserve = new WETH9(); StorageHistory history = new StorageHistory(); - gatekeeper = new Gatekeeper(existential, address(history)); + gatekeeper = new Gatekeeper(address(history)); gatekeeper.initialize(address(0)); history.setOwner(address(gatekeeper)); } - function redoGatekeeper(uint256 existential) external { - Gatekeeper newGatekeeper = new Gatekeeper(existential, address(0)); + function redoGatekeeper() external { + Gatekeeper newGatekeeper = new Gatekeeper(address(0)); newGatekeeper.initialize(address(gatekeeper)); address storageHistory = IGatekeeper(gatekeeper).storageHistory(); @@ -43,6 +46,11 @@ contract MockStaking is Test { _recalledAmounts[receiver] += amount; } + function recall(uint256 amount, uint256, uint256) external returns (address, uint256, uint256){ + _recalledAmounts[tx.origin] += amount; + return (address(mockReserve), amount, 0); + } + function recalledAmount(address who) external view returns (uint256) { return _recalledAmounts[who]; } @@ -54,14 +62,13 @@ contract GatekeeperStorageHistoryTest is Test { address constant ALICE = 0x0000000000000000000000000000000000000001; address constant BOB = 0x0000000000000000000000000000000000000002; uint256 constant INIT_AMOUNT = 1337 * 1e18; - uint256 constant EXISTENTIAL = 0; Gatekeeper gatekeeper; MockStaking staking; function setUp() public { vm.prank(ALICE); - staking = new MockStaking(EXISTENTIAL); + staking = new MockStaking(); staking.runGhost(bytes32(abi.encodePacked(ALICE)), INIT_AMOUNT); gatekeeper = staking.gatekeeper(); @@ -78,7 +85,7 @@ contract GatekeeperStorageHistoryTest is Test { } function test_historicalAmountsOnlyIncrease(uint256 ghostAmount, uint64 exodusSession) public { - vm.assume(ghostAmount > 0 && ghostAmount < INIT_AMOUNT); + vm.assume(ghostAmount > gatekeeper.EXISTENTIAL_DEPOSIT() && ghostAmount < INIT_AMOUNT); uint256 amountToGhost = ghostAmount; uint256 amountToMaterialize = ghostAmount / 2; @@ -99,6 +106,7 @@ contract GatekeeperStorageHistoryTest is Test { uint256 packed = RequestPacking.pack(0, uint64(block.chainid), BOB); uint256 previousAmount = staking.recalledAmount(BOB); + vm.prank(BOB, BOB); staking.runRecall(exodusSession, amountToMaterialize, packed); assertEq(previousAmount + amountToMaterialize, staking.recalledAmount(BOB)); @@ -121,7 +129,7 @@ contract GatekeeperStorageHistoryTest is Test { address prevStorageHistory = gatekeeper.storageHistory(); IStorageHistory.DeploymentSnapshot memory prevSnapshot = IStorageHistory(prevStorageHistory).deploymentSnapshot(); - staking.redoGatekeeper(EXISTENTIAL + 1); + staking.redoGatekeeper(); assert(gatekeeper != staking.gatekeeper()); address currStorageHistory = gatekeeper.storageHistory(); @@ -133,8 +141,5 @@ contract GatekeeperStorageHistoryTest is Test { assert(IStorageHistory(prevStorageHistory).isTransactionExecuted(exodusSession)); assert(IStorageHistory(currStorageHistory).isTransactionExecuted(exodusSession)); - - assertEq(gatekeeper.existentialDeposit(), EXISTENTIAL); - assertEq(staking.gatekeeper().existentialDeposit(), EXISTENTIAL + 1); } } diff --git a/test/gatekeeper/GatekeeperRecall.t.sol b/test/gatekeeper/GatekeeperRecall.t.sol new file mode 100644 index 0000000..7a5cc44 --- /dev/null +++ b/test/gatekeeper/GatekeeperRecall.t.sol @@ -0,0 +1,203 @@ +pragma solidity 0.8.20; + +import {Test} from "forge-std/Test.sol"; + +import {Fatso} from "../../src/FatsoERC20.sol"; +import {Stinky} from "../../src/StinkyERC20.sol"; +import {Ghost} from "../../src/GhstERC20.sol"; +import {GhostAuthority} from "../../src/GhostAuthority.sol"; +import {GhostTreasury} from "../../src/Treasury.sol"; +import {GhostStaking} from "../../src/Staking.sol"; +import {GhostBondDepository} from "../../src/BondDepository.sol"; +import {ERC20Mock} from "../../src/mocks/ERC20Mock.sol"; +import {WETH9} from "../../src/mocks/WETH9.sol"; +import {GhostBondingCalculator} from "../../src/StandardBondingCalculator.sol"; +import {Gatekeeper} from "../../src/Gatekeeper.sol"; + +import {ITreasury} from "../../src/interfaces/ITreasury.sol"; +import {IGatekeeper} from "../../src/interfaces/IGatekeeper.sol"; +import {IERC20} from "@openzeppelin-contracts/token/ERC20/IERC20.sol"; + +contract GatekeeperRecallTest is Test { + uint256 public constant TOTAL_INITIAL_SUPPLY = 5000000000000000; + uint256 public constant LARGE_APPROVAL = 100000000000000000000000000000000; + uint256 public constant INITIAL_INDEX = 10819917194513808e56; + uint48 public constant EPOCH_LENGTH = 2200; + uint48 public constant EPOCH_NUMBER = 1; + uint48 public constant EPOCH_END_TIME = 1337; + + uint256 public constant INITIAL_MINT = 1000000000000000000000000; + uint256 public constant CAPACITY = 10000e9; + uint256 public constant INITIAL_PRICE = 400e9; + uint256 public constant BUFFER = 2e5; + + address constant INITIALIZER = 0x0000000000000000000000000000000000000001; + address constant GOVERNOR = 0x0000000000000000000000000000000000000003; + address constant GUARDIAN = 0x0000000000000000000000000000000000000004; + address constant POLICY = 0x0000000000000000000000000000000000000005; + address constant VAULT = 0x0000000000000000000000000000000000000006; + address constant ALICE = 0x0000000000000000000000000000000000000007; + address constant BOB = 0x0000000000000000000000000000000000000008; + + uint256 public constant VESTING = 100; + uint256 public constant TIME_TO_CONCLUSION = 60 * 60 * 24; + uint256 public constant DEPOSIT_INTERVAL = 60 * 60 * 4; + uint256 public constant TUNE_INTERVAL = 60 * 60; + + Fatso ftso; + Stinky stnk; + Ghost ghst; + GhostStaking staking; + GhostTreasury treasury; + GhostAuthority authority; + GhostBondingCalculator calculator; + WETH9 reserve; + + function setUp() public { + vm.startPrank(INITIALIZER, INITIALIZER); + reserve = new WETH9(); + authority = new GhostAuthority( + GOVERNOR, + GUARDIAN, + POLICY, + VAULT + ); + ftso = new Fatso(address(authority), "Fatso", "FTSO"); + stnk = new Stinky(INITIAL_INDEX, "Stinky", "STNK"); + ghst = new Ghost(address(stnk), "Ghost", "GHST"); + staking = new GhostStaking( + address(ftso), + address(stnk), + address(ghst), + EPOCH_LENGTH, + EPOCH_NUMBER, + EPOCH_END_TIME, + address(authority) + ); + treasury = new GhostTreasury(address(ftso), address(authority)); + calculator = new GhostBondingCalculator(address(ftso), 6000, 3); + stnk.initialize(address(staking), address(treasury), address(ghst)); + ghst.initialize(address(staking)); + vm.stopPrank(); + + vm.startPrank(GOVERNOR); + authority.pushVault(address(treasury)); + treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, ALICE, address(0)); + treasury.enable(ITreasury.STATUS.RESERVETOKEN, address(reserve), address(calculator)); + treasury.enable(ITreasury.STATUS.STAKING, address(staking), address(0)); + vm.stopPrank(); + + vm.deal(ALICE, INITIAL_MINT); + + vm.startPrank(ALICE); + reserve.deposit{value: INITIAL_MINT}(); + reserve.approve(address(treasury), type(uint256).max); + treasury.deposit(address(reserve), INITIAL_MINT, treasury.tokenValue(address(reserve), INITIAL_MINT) / 2); + assertEq(ftso.totalSupply(), treasury.baseSupply()); + vm.stopPrank(); + } + + function test_recallChainWorks() public { + vm.startPrank(INITIALIZER); + Gatekeeper gatekeeper = Gatekeeper(payable(staking.gatekeeper())); + gatekeeper.updatePublicKeyMetadata(0, 0x4e8c1fe96d6737cdabbcc96501d6656b9d0b659b3a528ef507f2d52bef29e157, 0); + vm.stopPrank(); + + vm.startPrank(ALICE); + uint256 aliceBalance = ftso.balanceOf(ALICE); + ftso.approve(address(staking), type(uint256).max); + staking.stake(aliceBalance, ALICE, false, true); + + uint256 ghostBalance = ghst.balanceOf(ALICE); + staking.ghost(bytes32(abi.encodePacked(ALICE)), ghostBalance); + vm.stopPrank(); + + uint256 bountyPercent = type(uint32).max / 2; + uint256 amountToBridge = 42 * 1e15; + address evmReceiver = address(0x0000000000000000000000000000000000000002); + + uint256 bobGhstBefore = ghst.balanceOf(BOB); + uint256 receiverEthBefore = evmReceiver.balance; + uint256 receiverGhstBefore = ghst.balanceOf(evmReceiver); + uint256 totalReservesBefore = treasury.totalReserves(); + uint256 totalSupplyBefore = ftso.totalSupply(); + uint256 ghostedSupplyBefore = gatekeeper.ghostedSupply(); + + vm.txGasPrice(2 gwei); + vm.startPrank(BOB, BOB); + gatekeeper.verify( + hex"bf06188a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000009536c70891000000000000000000000000000000000000000000020000000000007a6980000000", + hex"046566d4b0904bf35afd25dff583d53bd30e50f57cc790ad08377e0b85006b38b85046b527098f3dfdadc30d6623b6b1c4644306dd56d39f7c9d6b3b295d005c33", + 0x942fb44ad0422c197f9c3016ff7c7e574a9f86182c5485e39fc9bebf61228ad6 + ); + vm.stopPrank(); + + { + uint256 bobEarnedGhst = ghst.balanceOf(BOB) - bobGhstBefore; + assertTrue(bobEarnedGhst > 0); + + uint256 bobEarnedFtso = ghst.balanceFrom(bobEarnedGhst); + + uint256 totalReservesAfter = treasury.totalReserves(); + uint256 totalSupplyAfter = ftso.totalSupply(); + + uint256 gasUsed = 2 * 1e9 * 329188; + uint256 gasReserveValue = treasury.tokenValue(address(reserve), gasUsed); + uint256 expectedGasFtso = gasReserveValue * totalSupplyAfter / totalReservesAfter; + + uint256 simulatedGhst = ghst.balanceTo(expectedGasFtso); + uint256 dynamicGasPriceEstimation = ghst.balanceFrom(simulatedGhst); + + assertApproxEqAbs(bobEarnedFtso, dynamicGasPriceEstimation, 1); + } + + { + uint256 expectedBounty = amountToBridge * bountyPercent / type(uint32).max; + uint256 expectedMintToReceiver = amountToBridge - expectedBounty; + uint256 actualMintToReceiver = ghst.balanceOf(evmReceiver) - receiverGhstBefore; + assertApproxEqAbs(actualMintToReceiver, expectedMintToReceiver, 1); + } + + { + uint256 receiverEthAfter = evmReceiver.balance; + uint256 receivedEth = receiverEthAfter - receiverEthBefore; + assertTrue(receivedEth > 0); + + uint256 totalReservesAfter = treasury.totalReserves(); + uint256 totalSupplyAfter = ftso.totalSupply(); + + uint256 expectedBounty = amountToBridge * bountyPercent / type(uint32).max; + uint256 totalBountyFtso = ghst.balanceFrom(expectedBounty); + uint256 totalBountyReserveValue = totalBountyFtso * totalReservesAfter / totalSupplyAfter; + + uint256 fraction = calculator.fraction(); + uint256 totalBountyInEth = totalBountyReserveValue * 1e18 / fraction; + totalBountyInEth = totalBountyInEth * 1e18 / 1e9; + + uint256 physicalGasSpentEth = 2 * 1e9 * 329188; // 2 gwei * gas Used + assertApproxEqAbs(receivedEth, totalBountyInEth - physicalGasSpentEth, 1); + } + + { + uint256 totalReservesAfter = treasury.totalReserves(); + uint256 totalSupplyAfter = ftso.totalSupply(); + + uint256 backingRatioBefore = totalReservesBefore * 1e18 / totalSupplyBefore; + uint256 backingRatioAfter = totalReservesAfter * 1e18 / totalSupplyAfter; + uint256 receivedValue = treasury.tokenValue(address(reserve), evmReceiver.balance); + + assertEq(backingRatioAfter, backingRatioBefore); + assertApproxEqAbs(totalReservesAfter + receivedValue, totalReservesBefore, 2000); // 2e-16% + + vm.prank(GOVERNOR); + treasury.auditReserves(); + assertEq(treasury.totalReserves() + receivedValue, totalReservesBefore); + } + + { + uint256 expectedMintToReceiver = amountToBridge * (type(uint32).max - bountyPercent) / type(uint32).max; + uint256 bobGhstAfter = ghst.balanceOf(BOB); + assertApproxEqAbs(ghostedSupplyBefore - bobGhstAfter - expectedMintToReceiver, gatekeeper.ghostedSupply(), 1); + } + } +} diff --git a/test/gatekeeper/GatekeeperWeaver.t.sol b/test/gatekeeper/GatekeeperWeaver.t.sol index 80ffb4d..4891eb9 100644 --- a/test/gatekeeper/GatekeeperWeaver.t.sol +++ b/test/gatekeeper/GatekeeperWeaver.t.sol @@ -13,9 +13,9 @@ contract MockStaking { GatekeeperWeaver public gatekeeper; address public governor; - constructor(uint256 existential) { + constructor() { StorageHistory history = new StorageHistory(); - gatekeeper = new GatekeeperWeaver(existential, address(history)); + gatekeeper = new GatekeeperWeaver(address(history)); gatekeeper.initialize(address(0)); history.setOwner(address(gatekeeper)); governor = msg.sender; @@ -26,10 +26,10 @@ contract MockStaking { return gatekeeper.ghost(receiver, amount); } - function createNewGatekeeper(uint256 existential) external { + function createNewGatekeeper() external { require(msg.sender == governor); - GatekeeperWeaver newGatekeeper = new GatekeeperWeaver(existential, address(0)); + GatekeeperWeaver newGatekeeper = new GatekeeperWeaver(address(0)); newGatekeeper.initialize(address(gatekeeper)); address storageHistory = IGatekeeper(gatekeeper).storageHistory(); @@ -43,7 +43,7 @@ contract GatekeeperWeaver is Gatekeeper { using Checkpoints for Checkpoints.Trace256; using Checkpoints for Checkpoints.Trace160; - constructor(uint256 existential, address storageHistory) Gatekeeper(existential, storageHistory) {} + constructor(address storageHistory) Gatekeeper(storageHistory) {} function filledEntries(uint256 session) public view returns (uint256) { return _filledEntries[session]; @@ -115,7 +115,6 @@ contract GatekeeperWeaver is Gatekeeper { contract GatekeeperWeaverTest is Test { address constant ALICE = 0x0000000000000000000000000000000000000001; address constant BOB = 0x0000000000000000000000000000000000000002; - uint256 constant EXISTENTIAL = 1337; uint256 constant AMOUNT = 1 * 1e7; MockStaking staking; @@ -123,7 +122,7 @@ contract GatekeeperWeaverTest is Test { function setUp() public { vm.prank(ALICE); - staking = new MockStaking(EXISTENTIAL); + staking = new MockStaking(); gatekeeper = staking.gatekeeper(); } @@ -164,7 +163,7 @@ contract GatekeeperWeaverTest is Test { vm.roll(block.number + 420); vm.prank(ALICE); - staking.createNewGatekeeper(EXISTENTIAL); + staking.createNewGatekeeper(); gatekeeper = staking.gatekeeper(); uint256 finalSession = gatekeeper.currentWeavingSession(); @@ -256,13 +255,15 @@ contract GatekeeperWeaverTest is Test { } } - function _prepareArrays(uint256 count) private pure returns (bytes32[] memory, uint256[] memory) { + function _prepareArrays(uint256 count) private view returns (bytes32[] memory, uint256[] memory) { bytes32[] memory whos = new bytes32[](count); uint256[] memory amounts = new uint256[](count); + uint256 existential = gatekeeper.EXISTENTIAL_DEPOSIT(); + for (uint256 i = 0; i < count; i++) { whos[i] = keccak256(abi.encodePacked("user", i)); - amounts[i] = EXISTENTIAL + 1 + i; + amounts[i] = existential + 1 + i; } return (whos, amounts); diff --git a/test/staking/Staking.t.sol b/test/staking/Staking.t.sol index 703c783..e3316d5 100644 --- a/test/staking/Staking.t.sol +++ b/test/staking/Staking.t.sol @@ -106,10 +106,9 @@ contract StakingTest is Test { EPOCH_LENGTH, EPOCH_NUMBER, EPOCH_END_TIME, - address(authority), - 0 + address(authority) ); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); stnk.initialize(address(staking), address(treasury), address(ghst)); ghst.initialize(address(staking)); calculator = new GhostBondingCalculator(address(ftso), 1, 1); @@ -596,7 +595,7 @@ contract StakingTest is Test { vm.prank(address(previousGatekeeper)); IStorageHistory(storageHistory).trySetTransactionExecuted(34); - Gatekeeper newGatekeeper = new Gatekeeper(420, address(0)); + Gatekeeper newGatekeeper = new Gatekeeper(address(0)); vm.prank(GOVERNOR); staking.updateGatekeeperAddress(address(newGatekeeper)); diff --git a/test/staking/StakingDistributor.t.sol b/test/staking/StakingDistributor.t.sol index 4c7be08..0a0e3b5 100644 --- a/test/staking/StakingDistributor.t.sol +++ b/test/staking/StakingDistributor.t.sol @@ -61,10 +61,9 @@ contract StakingDistributorTest is Test { EPOCH_LENGTH, EPOCH_NUMBER, EPOCH_END_TIME, - address(authority), - 0 + address(authority) ); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); calculator = new GhostBondingCalculator(address(ftso), 1, 1); distributor = new GhostDistributor( address(treasury), diff --git a/test/tokens/Ghst.t.sol b/test/tokens/Ghst.t.sol index 59d7fc7..ff0d3d9 100644 --- a/test/tokens/Ghst.t.sol +++ b/test/tokens/Ghst.t.sol @@ -53,8 +53,7 @@ contract GhostTest is 69, 1337, 1337, - address(authority), - 0 + address(authority) ); stnk.initialize(address(staking), TREASURY, address(ghst)); ghst.initialize(address(staking)); diff --git a/test/tokens/Stnk.t.sol b/test/tokens/Stnk.t.sol index 0e47c4a..beef784 100644 --- a/test/tokens/Stnk.t.sol +++ b/test/tokens/Stnk.t.sol @@ -59,8 +59,7 @@ contract StinkyTest is Test, ERC20PermitTest, ERC20AllowanceTest, ERC20TransferT 69, 1337, 1337, - address(authority), - 0 + address(authority) ); ghst.initialize(address(staking)); vm.stopPrank(); diff --git a/test/treasury/Treasury.t.sol b/test/treasury/Treasury.t.sol index 0d38913..9d26d49 100644 --- a/test/treasury/Treasury.t.sol +++ b/test/treasury/Treasury.t.sol @@ -37,7 +37,7 @@ contract GhostTreasuryTest is Test { reserve = new ERC20Mock("Reserve Token", "RET"); liquidity = new ERC20Mock("Liquidity Token", "LDT"); ftso = new Fatso(address(authority), "Fatso", "FTSO"); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); calculator = new GhostBondingCalculator(address(ftso), 1, 1); vm.stopPrank(); @@ -109,8 +109,8 @@ contract GhostTreasuryTest is Test { vm.prank(GOVERNOR); treasury.auditReserves(); - assertEq(treasury.permissions(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); - assertEq(treasury.registry(ITreasury.STATUS.RESERVETOKEN, 0), address(reserve)); + assertEq(treasury.permissioned(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); + assertEq(treasury.registered(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); assertEq( treasury.tokenValue(address(reserve), reserve.balanceOf(address(treasury))), treasury.totalReserves()); @@ -139,15 +139,13 @@ contract GhostTreasuryTest is Test { treasury.enable(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender, address(0)); vm.stopPrank(); - assertEq(treasury.registry(ITreasury.STATUS.RESERVETOKEN, 0), address(reserve)); - assertEq(treasury.registry(ITreasury.STATUS.LIQUIDITYTOKEN, 0), address(liquidity)); + assertEq(treasury.registered(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); + assertEq(treasury.registered(ITreasury.STATUS.LIQUIDITYTOKEN, address(liquidity)), true); assertEq(treasury.bondCalculator(address(liquidity)), address(calculator)); - vm.expectRevert(); - treasury.registry(ITreasury.STATUS.RESERVEDEPOSITOR, 0); - assertEq(treasury.permissions(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); - assertEq(treasury.permissions(ITreasury.STATUS.LIQUIDITYTOKEN, address(liquidity)), true); - assertEq(treasury.permissions(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender), true); + assertEq(treasury.permissioned(ITreasury.STATUS.RESERVETOKEN, address(reserve)), true); + assertEq(treasury.permissioned(ITreasury.STATUS.LIQUIDITYTOKEN, address(liquidity)), true); + assertEq(treasury.permissioned(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender), true); } function test_randomAddressCouldNotDisableStatusByAddress(address who) public { @@ -185,9 +183,9 @@ contract GhostTreasuryTest is Test { treasury.disable(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender); vm.stopPrank(); - assertEq(treasury.permissions(ITreasury.STATUS.RESERVETOKEN, address(reserve)), false); - assertEq(treasury.permissions(ITreasury.STATUS.LIQUIDITYTOKEN, address(liquidity)), false); - assertEq(treasury.permissions(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender), false); + assertEq(treasury.permissioned(ITreasury.STATUS.RESERVETOKEN, address(reserve)), false); + assertEq(treasury.permissioned(ITreasury.STATUS.LIQUIDITYTOKEN, address(liquidity)), false); + assertEq(treasury.permissioned(ITreasury.STATUS.RESERVEDEPOSITOR, msg.sender), false); } function test_mainnet_disableReserveAndLiquidity() public { diff --git a/test/treasury/TreasuryCoefficienBigger.sol b/test/treasury/TreasuryCoefficienBigger.sol index efe7053..c4fa4b6 100644 --- a/test/treasury/TreasuryCoefficienBigger.sol +++ b/test/treasury/TreasuryCoefficienBigger.sol @@ -41,7 +41,7 @@ contract GhostTreasuryCoefficienBiggerTest is Test { reserve = new ERC20Mock("Reserve Token", "RET"); liquidity = new ERC20Mock("Liquidity Token", "LDT"); ftso = new Fatso(address(authority), "Fatso", "FTSO"); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); calculator = new GhostBondingCalculator(address(ftso), 20, 1); vm.stopPrank(); diff --git a/test/treasury/TreasuryCoefficientLesser.sol b/test/treasury/TreasuryCoefficientLesser.sol index 29f12b5..0264e9e 100644 --- a/test/treasury/TreasuryCoefficientLesser.sol +++ b/test/treasury/TreasuryCoefficientLesser.sol @@ -41,7 +41,7 @@ contract GhostTreasuryCoefficientLesserTest is Test { reserve = new ERC20Mock("Reserve Token", "RET"); liquidity = new ERC20Mock("Liquidity Token", "LDT"); ftso = new Fatso(address(authority), "Fatso", "FTSO"); - treasury = new GhostTreasury(address(ftso), 69, address(authority)); + treasury = new GhostTreasury(address(ftso), address(authority)); calculator = new GhostBondingCalculator(address(ftso), 1, 20); vm.stopPrank(); diff --git a/test/treasury/TreasuryRedemption.t.sol b/test/treasury/TreasuryRedemption.t.sol index 42f2238..47f7f94 100644 --- a/test/treasury/TreasuryRedemption.t.sol +++ b/test/treasury/TreasuryRedemption.t.sol @@ -37,7 +37,7 @@ contract GhostTreasuryRedemptionTest is Test { OWNER, OWNER ); - treasury = new GhostTreasury(DAI, 69, address(authority)); + treasury = new GhostTreasury(DAI, address(authority)); calculator = new GhostBondingCalculator(DAI, 4000, 1); vm.stopPrank();