Compare commits
4 Commits
b87dff4c7a
...
1359f920ca
| Author | SHA1 | Date | |
|---|---|---|---|
| 1359f920ca | |||
| d7977a5ddc | |||
| 44636659e3 | |||
| d3d6912590 |
@ -137,6 +137,15 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
|
|||||||
bool validSignature = Verifier.verifyGhost(call, px, rx, s);
|
bool validSignature = Verifier.verifyGhost(call, px, rx, s);
|
||||||
if (!validSignature) revert BadSignature();
|
if (!validSignature) revert BadSignature();
|
||||||
|
|
||||||
|
bytes4 selector = bytes4(call[:4]);
|
||||||
|
if (
|
||||||
|
selector != this.recall.selector &&
|
||||||
|
selector != this.rotate.selector &&
|
||||||
|
selector != this.govern.selector
|
||||||
|
) {
|
||||||
|
revert InvalidSelector();
|
||||||
|
}
|
||||||
|
|
||||||
(bool success,) = address(this).call(call);
|
(bool success,) = address(this).call(call);
|
||||||
if (!success) revert ExecutionReverted();
|
if (!success) revert ExecutionReverted();
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
|
|
||||||
uint256 private _lastRebaseBlock;
|
uint256 private _lastRebaseBlock;
|
||||||
|
|
||||||
mapping(address => bool) public locks;
|
mapping(address => bool) public unlocks;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address _ftso,
|
address _ftso,
|
||||||
@ -79,12 +79,14 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
bool isRebase,
|
bool isRebase,
|
||||||
bool isClaim
|
bool isClaim
|
||||||
) external override returns (uint256 returnAmount) {
|
) external override returns (uint256 returnAmount) {
|
||||||
returnAmount = amount + rebase();
|
if (!unlocks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
||||||
|
|
||||||
|
returnAmount = amount + this.rebase();
|
||||||
IERC20(ftso).safeTransferFrom(msg.sender, address(this), amount);
|
IERC20(ftso).safeTransferFrom(msg.sender, address(this), amount);
|
||||||
|
|
||||||
if (isClaim && warmupPeriod == 0) {
|
if (isClaim && warmupPeriod == 0) {
|
||||||
returnAmount = _sendStnkBased(returnAmount, to, isRebase);
|
returnAmount = _sendStnkBased(returnAmount, to, isRebase);
|
||||||
} else {
|
} else {
|
||||||
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(returnAmount, to, expiry);
|
||||||
}
|
}
|
||||||
@ -92,7 +94,7 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function claim(address to, bool isRebase) public override returns (uint256) {
|
function claim(address to, bool isRebase) public override returns (uint256) {
|
||||||
if (locks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
if (!unlocks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
||||||
uint256 claimedAmount = IGhostWarmup(warmup).claim(to, epoch.number);
|
uint256 claimedAmount = IGhostWarmup(warmup).claim(to, epoch.number);
|
||||||
return _sendGhstBased(claimedAmount, to, isRebase);
|
return _sendGhstBased(claimedAmount, to, isRebase);
|
||||||
}
|
}
|
||||||
@ -102,7 +104,7 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
uint256 amount,
|
uint256 amount,
|
||||||
bool isRebase
|
bool isRebase
|
||||||
) public override returns (uint256) {
|
) public override returns (uint256) {
|
||||||
if (locks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
if (!unlocks[to] && to != msg.sender) revert ExternalDepositsLocked();
|
||||||
uint256 claimedAmount = IGhostWarmup(warmup).claimByAmount(to, amount, epoch.number);
|
uint256 claimedAmount = IGhostWarmup(warmup).claimByAmount(to, amount, epoch.number);
|
||||||
return _sendGhstBased(claimedAmount, to, isRebase);
|
return _sendGhstBased(claimedAmount, to, isRebase);
|
||||||
}
|
}
|
||||||
@ -121,7 +123,7 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleLock() external override {
|
function toggleLock() external override {
|
||||||
locks[msg.sender] = !locks[msg.sender];
|
unlocks[msg.sender] = !unlocks[msg.sender];
|
||||||
}
|
}
|
||||||
|
|
||||||
function unstake(
|
function unstake(
|
||||||
@ -130,12 +132,14 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
bool isTrigger,
|
bool isTrigger,
|
||||||
bool isRebase
|
bool isRebase
|
||||||
) external override returns (uint256) {
|
) external override returns (uint256) {
|
||||||
amount += isTrigger ? rebase() : 0;
|
uint256 extraAmount = isTrigger ? this.rebase() : 0;
|
||||||
|
|
||||||
if (isRebase) {
|
if (isRebase) {
|
||||||
|
amount += extraAmount;
|
||||||
ISTNK(stnk).safeTransferFrom(msg.sender, address(this), amount);
|
ISTNK(stnk).safeTransferFrom(msg.sender, address(this), amount);
|
||||||
} else {
|
} else {
|
||||||
IGHST(ghst).burn(msg.sender, amount);
|
IGHST(ghst).burn(msg.sender, amount);
|
||||||
amount = IGHST(ghst).balanceFrom(amount);
|
amount = IGHST(ghst).balanceFrom(amount) + extraAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount > IERC20(ftso).balanceOf(address(this))) revert InsufficientBalance();
|
if (amount > IERC20(ftso).balanceOf(address(this))) revert InsufficientBalance();
|
||||||
@ -211,7 +215,9 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
|
|
||||||
if (distributor != address(0)) {
|
if (distributor != address(0)) {
|
||||||
IDistributor(distributor).distribute();
|
IDistributor(distributor).distribute();
|
||||||
bounty = IDistributor(distributor).retrieveBounty();
|
if (msg.sender == address(this)) {
|
||||||
|
bounty = IDistributor(distributor).retrieveBounty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 balance = IERC20(ftso).balanceOf(address(this));
|
uint256 balance = IERC20(ftso).balanceOf(address(this));
|
||||||
@ -258,9 +264,9 @@ contract GhostStaking is IStaking, GhostAccessControlled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function warmupInfo(address who) external view returns (uint256, uint256, uint48, bool) {
|
function warmupInfo(address who) external view returns (uint256, uint256, uint48, bool) {
|
||||||
bool lock = locks[who];
|
|
||||||
(uint256 deposit, uint256 payout, uint48 expiry) = IGhostWarmup(warmup).warmupInfo(who);
|
(uint256 deposit, uint256 payout, uint48 expiry) = IGhostWarmup(warmup).warmupInfo(who);
|
||||||
return (deposit, payout, expiry, lock);
|
bool matured = expiry > 0 && epoch.number >= expiry;
|
||||||
|
return (deposit, payout, expiry, matured);
|
||||||
}
|
}
|
||||||
|
|
||||||
function totalReserves() external override view returns (uint256) {
|
function totalReserves() external override view returns (uint256) {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ interface IGatekeeper {
|
|||||||
error BadSignature();
|
error BadSignature();
|
||||||
error NotGatekeeper();
|
error NotGatekeeper();
|
||||||
error AlreadyExecuted();
|
error AlreadyExecuted();
|
||||||
|
error InvalidSelector();
|
||||||
error InvalidCalldata();
|
error InvalidCalldata();
|
||||||
error InvalidPublicKey();
|
error InvalidPublicKey();
|
||||||
error NonExistentAmount();
|
error NonExistentAmount();
|
||||||
|
|||||||
@ -25,7 +25,6 @@ abstract contract NoteKeeper is INoteKeeper {
|
|||||||
_GHST = IGHST(_ghstAddress);
|
_GHST = IGHST(_ghstAddress);
|
||||||
_STAKING = IStaking(_stakingAddress);
|
_STAKING = IStaking(_stakingAddress);
|
||||||
_TREASURY = ITreasury(_treasuryAddress);
|
_TREASURY = ITreasury(_treasuryAddress);
|
||||||
_STAKING.toggleLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNote(
|
function addNote(
|
||||||
|
|||||||
@ -548,7 +548,7 @@ contract GhostBondDepositoryTest is Test {
|
|||||||
(, uint256 payout,, bool matured) = staking.warmupInfo(address(depository));
|
(, uint256 payout,, bool matured) = staking.warmupInfo(address(depository));
|
||||||
assertEq(ghst.balanceOf(address(depository)) > 0, true);
|
assertEq(ghst.balanceOf(address(depository)) > 0, true);
|
||||||
assertEq(payout > 0, true);
|
assertEq(payout > 0, true);
|
||||||
assertEq(matured, true);
|
assertEq(matured, false);
|
||||||
|
|
||||||
vm.prank(BOB);
|
vm.prank(BOB);
|
||||||
depository.forceRedeemAll(bytes32(0));
|
depository.forceRedeemAll(bytes32(0));
|
||||||
|
|||||||
@ -179,11 +179,11 @@ contract StakingTest is Test {
|
|||||||
assertEq(ftso.balanceOf(ALICE), 0);
|
assertEq(ftso.balanceOf(ALICE), 0);
|
||||||
assertApproxEqAbs(staking.supplyInWarmup(), rebased, 1);
|
assertApproxEqAbs(staking.supplyInWarmup(), rebased, 1);
|
||||||
|
|
||||||
(uint256 deposit, uint256 payout, uint48 expiry, bool lock) = staking.warmupInfo(ALICE);
|
(uint256 deposit, uint256 payout, uint48 expiry, bool matured) = staking.warmupInfo(ALICE);
|
||||||
assertEq(deposit, AMOUNT);
|
assertEq(deposit, AMOUNT);
|
||||||
assertEq(payout, ghst.balanceTo(AMOUNT));
|
assertEq(payout, ghst.balanceTo(AMOUNT));
|
||||||
assertEq(expiry, 1);
|
assertEq(expiry, 1);
|
||||||
assertEq(lock, false);
|
assertEq(matured, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_stake_emitsStakedEvent() public {
|
function test_stake_emitsStakedEvent() public {
|
||||||
@ -227,15 +227,17 @@ contract StakingTest is Test {
|
|||||||
assertEq(ftso.balanceOf(ALICE), 0);
|
assertEq(ftso.balanceOf(ALICE), 0);
|
||||||
assertApproxEqAbs(staking.supplyInWarmup(), rebased, 1);
|
assertApproxEqAbs(staking.supplyInWarmup(), rebased, 1);
|
||||||
|
|
||||||
(uint256 deposit, uint256 payout, uint48 expiry, bool lock) = staking.warmupInfo(ALICE);
|
(uint256 deposit, uint256 payout, uint48 expiry, bool matured) = staking.warmupInfo(ALICE);
|
||||||
assertEq(deposit, AMOUNT);
|
assertEq(deposit, AMOUNT);
|
||||||
assertEq(payout, ghst.balanceTo(AMOUNT));
|
assertEq(payout, ghst.balanceTo(AMOUNT));
|
||||||
assertEq(expiry, 2);
|
assertEq(expiry, 2);
|
||||||
assertEq(lock, false);
|
assertEq(matured, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_stake_allowsSelfDepositWhenNotLocked() public {
|
function test_stake_allowsSelfDepositWhenNotLocked() public {
|
||||||
_mintAndApprove(ALICE, AMOUNT);
|
_mintAndApprove(ALICE, AMOUNT);
|
||||||
|
vm.prank(BOB);
|
||||||
|
staking.toggleLock();
|
||||||
|
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
staking.stake(AMOUNT, BOB, false, false);
|
staking.stake(AMOUNT, BOB, false, false);
|
||||||
@ -245,8 +247,6 @@ contract StakingTest is Test {
|
|||||||
|
|
||||||
function test_stake_disablesExternalDepositsWhenLocked() public {
|
function test_stake_disablesExternalDepositsWhenLocked() public {
|
||||||
_mintAndApprove(ALICE, AMOUNT);
|
_mintAndApprove(ALICE, AMOUNT);
|
||||||
vm.prank(BOB);
|
|
||||||
staking.toggleLock();
|
|
||||||
|
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
@ -279,9 +279,6 @@ contract StakingTest is Test {
|
|||||||
_prepareAndRoll(ALICE, AMOUNT, false, false);
|
_prepareAndRoll(ALICE, AMOUNT, false, false);
|
||||||
|
|
||||||
assertEq(ghst.balanceOf(ALICE), 0);
|
assertEq(ghst.balanceOf(ALICE), 0);
|
||||||
vm.prank(ALICE);
|
|
||||||
staking.toggleLock();
|
|
||||||
|
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
vm.prank(BOB);
|
vm.prank(BOB);
|
||||||
staking.claim(ALICE, false);
|
staking.claim(ALICE, false);
|
||||||
@ -290,6 +287,8 @@ contract StakingTest is Test {
|
|||||||
|
|
||||||
function test_claim_allowExternalClaimsWhenNotLocked() public {
|
function test_claim_allowExternalClaimsWhenNotLocked() public {
|
||||||
_prepareAndRoll(ALICE, AMOUNT, false, false);
|
_prepareAndRoll(ALICE, AMOUNT, false, false);
|
||||||
|
vm.prank(ALICE);
|
||||||
|
staking.toggleLock();
|
||||||
|
|
||||||
assertEq(ghst.balanceOf(ALICE), 0);
|
assertEq(ghst.balanceOf(ALICE), 0);
|
||||||
vm.prank(BOB);
|
vm.prank(BOB);
|
||||||
@ -577,7 +576,7 @@ contract StakingTest is Test {
|
|||||||
(,,, uint256 distribute) = staking.epoch();
|
(,,, uint256 distribute) = staking.epoch();
|
||||||
assertEq(distribute, postBounty);
|
assertEq(distribute, postBounty);
|
||||||
assertEq(stnk.balanceOf(ALICE), postBounty);
|
assertEq(stnk.balanceOf(ALICE), postBounty);
|
||||||
assertEq(ftso.balanceOf(address(staking)), 2 * postBounty + bounty);
|
assertEq(ftso.balanceOf(address(staking)), 2 * postBounty);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_arbitraryAddressCouldNotAddGatekeeper(address someone, address maybeGatekeeper) public {
|
function test_arbitraryAddressCouldNotAddGatekeeper(address someone, address maybeGatekeeper) public {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user