make gatekeeper to store historical bridging information
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
6350f8cfba
commit
53928fa63c
@ -102,8 +102,16 @@ GOVERNOR_VOTING_PERIOD=
|
|||||||
GOVERNOR_PROPOSAL_THRESHOLD=
|
GOVERNOR_PROPOSAL_THRESHOLD=
|
||||||
GOVERNOR_QUORUM_FRACTION=
|
GOVERNOR_QUORUM_FRACTION=
|
||||||
|
|
||||||
## Initial ghosted supply on gatekeeper
|
###################### Initial ghosted supply on gatekeeper ##########################
|
||||||
|
## ghostedSupply - supply that is currently locked inside the gatekeeper ##
|
||||||
|
## ghostedIn - historical supply that was bridged in (max value is 2^104) ##
|
||||||
|
## ghostedOut - historical supply that was bridged out (max value is 2^104) ##
|
||||||
|
## deployedAt - time when gatekeepers was deployed, could be inherited if needed ##
|
||||||
|
######################################################################################
|
||||||
INITIAL_GHOSTED_SUPPLY=
|
INITIAL_GHOSTED_SUPPLY=
|
||||||
|
INITIAL_GHOSTED_IN=
|
||||||
|
INITIAL_GHOSTED_OUT=
|
||||||
|
GATEKEEPER_DEPLOYED_AT=
|
||||||
|
|
||||||
SEPOLIA_TEST_RPC_URL=
|
SEPOLIA_TEST_RPC_URL=
|
||||||
SEPOLIA_TEST_API_KEY=
|
SEPOLIA_TEST_API_KEY=
|
||||||
|
|||||||
@ -43,6 +43,4 @@ mordor-testnet = "${MORDOR_TEST_RPC_URL}"
|
|||||||
[etherscan]
|
[etherscan]
|
||||||
sepolia-testnet = { key = "${SEPOLIA_TEST_API_KEY}", url = "${SEPOLIA_TEST_ENDPOINT}" }
|
sepolia-testnet = { key = "${SEPOLIA_TEST_API_KEY}", url = "${SEPOLIA_TEST_ENDPOINT}" }
|
||||||
hoodi-testnet = { key = "${HOODI_TEST_API_KEY}", url = "${HOODI_TEST_ENDPOINT}" }
|
hoodi-testnet = { key = "${HOODI_TEST_API_KEY}", url = "${HOODI_TEST_ENDPOINT}" }
|
||||||
|
mordor-testnet = { key = "${MORDOR_TEST_API_KEY}", url = "${MORDOR_TEST_ENDPOINT}", verifier = "blockscout" }
|
||||||
[verifiers]
|
|
||||||
mordor-testnet = { verifier = "blockscout", url = "${MORDOR_TEST_ENDPOINT}" }
|
|
||||||
|
|||||||
@ -2,25 +2,42 @@
|
|||||||
pragma solidity ^0.8.20;
|
pragma solidity ^0.8.20;
|
||||||
|
|
||||||
import {IGatekeeper} from "./interfaces/IGatekeeper.sol";
|
import {IGatekeeper} from "./interfaces/IGatekeeper.sol";
|
||||||
|
import {IGatekeeperMetadata} from "./interfaces/IGatekeeperMetadata.sol";
|
||||||
|
|
||||||
|
contract Gatekeeper is IGatekeeper, IGatekeeperMetadata {
|
||||||
|
uint256 public constant DIVISOR = 1e6;
|
||||||
|
|
||||||
contract Gatekeeper is IGatekeeper {
|
|
||||||
uint256 public override ghostedSupply;
|
uint256 public override ghostedSupply;
|
||||||
address public immutable staking; // forge-lint: disable-line(screaming-snake-case-immutable)
|
address public immutable staking; // forge-lint: disable-line(screaming-snake-case-immutable)
|
||||||
|
|
||||||
|
GatekeeperMetadata private _metadata;
|
||||||
uint256 private _aggregatedPublicKey;
|
uint256 private _aggregatedPublicKey;
|
||||||
mapping(uint256 => mapping(uint256 => bool)) private _executedTransaction;
|
mapping(uint256 => mapping(uint256 => bool)) private _executedTransaction;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address _staking,
|
address _staking,
|
||||||
uint256 _ghostedSupply
|
uint256 _ghostedSupply,
|
||||||
|
uint48 _deployedAt,
|
||||||
|
uint104 _amountIn,
|
||||||
|
uint104 _amountOut
|
||||||
) {
|
) {
|
||||||
ghostedSupply = _ghostedSupply;
|
ghostedSupply = _ghostedSupply;
|
||||||
staking = _staking;
|
staking = _staking;
|
||||||
|
_metadata = GatekeeperMetadata({
|
||||||
|
deployedAt: _deployedAt,
|
||||||
|
amountIn: _amountIn,
|
||||||
|
amountOut: _amountOut
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadata() external view returns (GatekeeperMetadata memory) {
|
||||||
|
return _metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ghost(bytes32 receiver, uint256 amount) external override {
|
function ghost(bytes32 receiver, uint256 amount) external override {
|
||||||
if (msg.sender != staking) revert NotStaking();
|
if (msg.sender != staking) revert NotStaking();
|
||||||
ghostedSupply += amount;
|
ghostedSupply += amount;
|
||||||
|
_metadata.amountIn += uint104(amount); // forge-lint: disable-line(unsafe-typecast)
|
||||||
emit Ghosted(receiver, amount);
|
emit Ghosted(receiver, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +62,7 @@ contract Gatekeeper is IGatekeeper {
|
|||||||
|
|
||||||
if (_incorrectSignature(rx, s, message)) revert WrongSignature();
|
if (_incorrectSignature(rx, s, message)) revert WrongSignature();
|
||||||
ghostedSupply -= amount;
|
ghostedSupply -= amount;
|
||||||
|
_metadata.amountIn += uint104(amount); // forge-lint: disable-line(unsafe-typecast)
|
||||||
emit Materialized(receiver, amount);
|
emit Materialized(receiver, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
src/interfaces/IGatekeeperMetadata.sol
Normal file
12
src/interfaces/IGatekeeperMetadata.sol
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.20;
|
||||||
|
|
||||||
|
interface IGatekeeperMetadata {
|
||||||
|
struct GatekeeperMetadata {
|
||||||
|
uint48 deployedAt;
|
||||||
|
uint104 amountIn;
|
||||||
|
uint104 amountOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
function metadata() external view returns (GatekeeperMetadata memory);
|
||||||
|
}
|
||||||
@ -13,14 +13,14 @@ contract GatekeeperTest is Test {
|
|||||||
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
gatekeeper = new Gatekeeper(ALICE, 0);
|
gatekeeper = new Gatekeeper(ALICE, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_correctInitialization() public {
|
function test_correctInitialization() public {
|
||||||
assertEq(gatekeeper.staking(), ALICE);
|
assertEq(gatekeeper.staking(), ALICE);
|
||||||
assertEq(gatekeeper.ghostedSupply(), 0);
|
assertEq(gatekeeper.ghostedSupply(), 0);
|
||||||
|
|
||||||
Gatekeeper anotherGatekeeper = new Gatekeeper(BOB, INIT_AMOUNT);
|
Gatekeeper anotherGatekeeper = new Gatekeeper(BOB, INIT_AMOUNT, 0, 0, 0);
|
||||||
assertEq(anotherGatekeeper.staking(), BOB);
|
assertEq(anotherGatekeeper.staking(), BOB);
|
||||||
assertEq(anotherGatekeeper.ghostedSupply(), INIT_AMOUNT);
|
assertEq(anotherGatekeeper.ghostedSupply(), INIT_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|||||||
55
test/gatekeeper/GatekeeperMetadata.t.sol
Normal file
55
test/gatekeeper/GatekeeperMetadata.t.sol
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
pragma solidity 0.8.20;
|
||||||
|
|
||||||
|
import {Test} from "forge-std/Test.sol";
|
||||||
|
|
||||||
|
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
||||||
|
|
||||||
|
contract GatekeeperMetadataTest is Test {
|
||||||
|
address constant ALICE = 0x0000000000000000000000000000000000000001;
|
||||||
|
uint256 constant INIT_AMOUNT = 69 * 1e18;
|
||||||
|
uint256 constant INIT_GHOSTED = type(uint104).max / 2;
|
||||||
|
uint48 constant DEPLOYED_AT = 1337;
|
||||||
|
uint104 constant AMOUNT_IN = 69;
|
||||||
|
uint104 constant AMOUNT_OUT = 420;
|
||||||
|
|
||||||
|
Gatekeeper gatekeeper;
|
||||||
|
|
||||||
|
function setUp() public {
|
||||||
|
gatekeeper = new Gatekeeper(ALICE, INIT_GHOSTED, DEPLOYED_AT, AMOUNT_IN, AMOUNT_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_correctMetadataInitialization() public view {
|
||||||
|
Gatekeeper.GatekeeperMetadata memory metadata = gatekeeper.metadata();
|
||||||
|
assertEq(metadata.deployedAt, DEPLOYED_AT);
|
||||||
|
assertEq(metadata.amountIn, AMOUNT_IN);
|
||||||
|
assertEq(metadata.amountOut, AMOUNT_OUT);
|
||||||
|
assertEq(gatekeeper.ghostedSupply(), INIT_GHOSTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_historicalAmountsOnlyIncrease(uint256 ghostAmount) public {
|
||||||
|
vm.assume(ghostAmount > 0 && ghostAmount < INIT_GHOSTED / 2);
|
||||||
|
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
||||||
|
uint256 ghostedSupply = gatekeeper.ghostedSupply();
|
||||||
|
|
||||||
|
Gatekeeper.GatekeeperMetadata memory metadata = gatekeeper.metadata();
|
||||||
|
uint104 amountIn = metadata.amountIn;
|
||||||
|
uint104 amountOut = metadata.amountOut;
|
||||||
|
|
||||||
|
if (ghostAmount % 2 == 0) {
|
||||||
|
vm.prank(ALICE);
|
||||||
|
gatekeeper.ghost(receiver, ghostAmount);
|
||||||
|
amountIn += uint104(ghostAmount); // forge-lint: disable-line(unsafe-typecast)
|
||||||
|
ghostedSupply += ghostAmount;
|
||||||
|
} else {
|
||||||
|
vm.expectRevert();
|
||||||
|
vm.prank(ALICE);
|
||||||
|
gatekeeper.materialize(ALICE, ghostAmount, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gatekeeper.GatekeeperMetadata memory newMetadata = gatekeeper.metadata();
|
||||||
|
assertEq(newMetadata.amountIn, amountIn);
|
||||||
|
assertEq(newMetadata.amountOut, amountOut);
|
||||||
|
assertEq(gatekeeper.ghostedSupply(), ghostedSupply);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -73,7 +73,7 @@ contract StakingTest is Test {
|
|||||||
treasury = new GhostTreasury(address(ftso), 69, address(authority));
|
treasury = new GhostTreasury(address(ftso), 69, address(authority));
|
||||||
stnk.initialize(address(staking), address(treasury), address(ghst));
|
stnk.initialize(address(staking), address(treasury), address(ghst));
|
||||||
ghst.initialize(address(staking));
|
ghst.initialize(address(staking));
|
||||||
gatekeeper = new Gatekeeper(address(staking), 0);
|
gatekeeper = new Gatekeeper(address(staking), 0, 0, 0, 0);
|
||||||
calculator = new GhostBondingCalculator(address(ftso), 1, 1);
|
calculator = new GhostBondingCalculator(address(ftso), 1, 1);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user