emit event during the weaver insertion
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
635853f170
commit
b1e9be968e
@ -109,14 +109,12 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
|
|||||||
return (publicKey, state.parity, state.session);
|
return (publicKey, state.parity, state.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ghost(bytes32 receiver, uint256 amount) external override returns (uint256) {
|
function ghost(bytes32 receiver, uint256 amount) external override {
|
||||||
if (msg.sender != staking) revert NotStaking();
|
if (msg.sender != staking) revert NotStaking();
|
||||||
if (amount < EXISTENTIAL_DEPOSIT) revert NonExistentAmount();
|
if (amount < EXISTENTIAL_DEPOSIT) revert NonExistentAmount();
|
||||||
|
|
||||||
IStorageHistory(storageHistory).increaseBridgeIn(amount);
|
IStorageHistory(storageHistory).increaseBridgeIn(amount);
|
||||||
|
_insertTreeNode(receiver, amount);
|
||||||
emit Ghosted(receiver, amount);
|
|
||||||
return _insertTreeNode(receiver, amount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify(
|
function verify(
|
||||||
|
|||||||
@ -14,7 +14,6 @@ interface IGatekeeper {
|
|||||||
error InsufficientValue();
|
error InsufficientValue();
|
||||||
error ExecutionReverted();
|
error ExecutionReverted();
|
||||||
|
|
||||||
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
|
||||||
event Recalled(address indexed receiver, uint256 indexed amount);
|
event Recalled(address indexed receiver, uint256 indexed amount);
|
||||||
event Rotated(bytes32 indexed aggregatedPublicKey, uint8 indexed parity);
|
event Rotated(bytes32 indexed aggregatedPublicKey, uint8 indexed parity);
|
||||||
event VoluntaryVerification(address indexed sender, uint256 indexed gasSpent);
|
event VoluntaryVerification(address indexed sender, uint256 indexed gasSpent);
|
||||||
@ -29,6 +28,6 @@ interface IGatekeeper {
|
|||||||
function govern(uint256 session, uint256 payload, bytes calldata call) external returns (bytes calldata);
|
function govern(uint256 session, uint256 payload, bytes calldata call) external returns (bytes calldata);
|
||||||
function recall(uint256 session, uint256 amount, uint256 payload) external;
|
function recall(uint256 session, uint256 amount, uint256 payload) external;
|
||||||
function rotate(uint256 session, bytes32 publicKey, uint8 parity) external;
|
function rotate(uint256 session, bytes32 publicKey, uint8 parity) external;
|
||||||
function ghost(bytes32 receiver, uint256 amount) external returns (uint256);
|
function ghost(bytes32 receiver, uint256 amount) external;
|
||||||
function initialize(address previousAddress) external;
|
function initialize(address previousAddress) external;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
pragma solidity ^0.8.20;
|
pragma solidity ^0.8.20;
|
||||||
|
|
||||||
interface IWeaver {
|
interface IWeaver {
|
||||||
|
event ThreadInserted(uint256 index, uint256 session);
|
||||||
|
|
||||||
function currentWeavingSession() external view returns (uint256);
|
function currentWeavingSession() external view returns (uint256);
|
||||||
function startWeavingSession() external view returns (uint256);
|
function startWeavingSession() external view returns (uint256);
|
||||||
function getSlotValues(uint256 globalIndex, uint256 session, uint256 atBlock) external view returns (bytes32[] memory);
|
function getSlotValues(uint256 globalIndex, uint256 session, uint256 atBlock) external view returns (bytes32[] memory);
|
||||||
|
|||||||
@ -14,8 +14,8 @@ contract WeaverMock is Weaver {
|
|||||||
return _previousAddress;
|
return _previousAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertTreeNode(bytes32 receiver, uint256 amount) external returns (uint256) {
|
function insertTreeNode(bytes32 receiver, uint256 amount) external {
|
||||||
return _insertTreeNode(receiver, amount);
|
_insertTreeNode(receiver, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeArgumentsHash(
|
function computeArgumentsHash(
|
||||||
|
|||||||
@ -134,9 +134,10 @@ abstract contract Weaver is IWeaver {
|
|||||||
return proof;
|
return proof;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _insertTreeNode(bytes32 who, uint256 amount) internal returns (uint256 globalIndex) {
|
function _insertTreeNode(bytes32 who, uint256 amount) internal {
|
||||||
uint256 session = currentWeavingSession;
|
uint256 session = currentWeavingSession;
|
||||||
globalIndex = _filledEntries[session];
|
uint256 globalIndex = _filledEntries[session];
|
||||||
|
|
||||||
if (globalIndex >= ENTRIES) {
|
if (globalIndex >= ENTRIES) {
|
||||||
unchecked { ++session; }
|
unchecked { ++session; }
|
||||||
currentWeavingSession = session;
|
currentWeavingSession = session;
|
||||||
@ -158,6 +159,8 @@ abstract contract Weaver is IWeaver {
|
|||||||
_slotValues[session][slotIndex].push(preimage);
|
_slotValues[session][slotIndex].push(preimage);
|
||||||
|
|
||||||
unchecked { ++_filledEntries[session]; }
|
unchecked { ++_filledEntries[session]; }
|
||||||
|
|
||||||
|
emit ThreadInserted(globalIndex, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _computeArgumentsHash(uint256 i, uint256 a, bytes32 r) internal pure returns (bytes32) {
|
function _computeArgumentsHash(uint256 i, uint256 a, bytes32 r) internal pure returns (bytes32) {
|
||||||
|
|||||||
@ -203,7 +203,7 @@ contract GatekeeperTest is Test {
|
|||||||
Gatekeeper gatekeeper;
|
Gatekeeper gatekeeper;
|
||||||
MockStaking staking;
|
MockStaking staking;
|
||||||
|
|
||||||
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
event ThreadInserted(uint256 index, uint256 session);
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
vm.prank(ALICE, ALICE);
|
vm.prank(ALICE, ALICE);
|
||||||
@ -247,7 +247,7 @@ contract GatekeeperTest is Test {
|
|||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
||||||
|
|
||||||
vm.expectEmit(true, true, true, false, address(gatekeeper));
|
vm.expectEmit(true, true, true, false, address(gatekeeper));
|
||||||
emit Ghosted(receiver, ghostAmount);
|
emit ThreadInserted(0, 0);
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
staking.runGhost(receiver, ghostAmount);
|
staking.runGhost(receiver, ghostAmount);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
pragma solidity 0.8.20;
|
pragma solidity 0.8.20;
|
||||||
|
|
||||||
import {Test} from "forge-std/Test.sol";
|
import {Test, Vm} from "forge-std/Test.sol";
|
||||||
|
|
||||||
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
||||||
import {Hashes} from "../../src/libraries/Hashes.sol";
|
import {Hashes} from "../../src/libraries/Hashes.sol";
|
||||||
@ -21,9 +21,9 @@ contract MockStaking {
|
|||||||
governor = msg.sender;
|
governor = msg.sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ghost(bytes32 receiver, uint256 amount) external returns (uint256) {
|
function ghost(bytes32 receiver, uint256 amount) external {
|
||||||
require(msg.sender == governor);
|
require(msg.sender == governor);
|
||||||
return gatekeeper.ghost(receiver, amount);
|
gatekeeper.ghost(receiver, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewGatekeeper() external {
|
function createNewGatekeeper() external {
|
||||||
@ -127,25 +127,25 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function test_insertationWorksAsExpected() public {
|
function test_insertationWorksAsExpected() public {
|
||||||
uint256 currentWeavingSession = gatekeeper.currentWeavingSession();
|
|
||||||
uint256 maxCount = gatekeeper.ENTRIES();
|
uint256 maxCount = gatekeeper.ENTRIES();
|
||||||
|
uint256 currentWeavingSession;
|
||||||
|
uint256 newWeavingSession;
|
||||||
uint256 globalIndex;
|
uint256 globalIndex;
|
||||||
|
|
||||||
(bytes32[] memory whos, uint256[] memory amounts) = _prepareArrays(maxCount);
|
(bytes32[] memory whos, uint256[] memory amounts) = _prepareArrays(maxCount);
|
||||||
|
vm.recordLogs();
|
||||||
|
|
||||||
for (uint256 i = 0; i < maxCount; i++) {
|
for (uint256 i = 0; i < maxCount; i++) {
|
||||||
if (i % 5 == 0) { vm.roll(block.number + 1); }
|
if (i % 5 == 0) { vm.roll(block.number + 1); }
|
||||||
globalIndex = _insertWithAssert(currentWeavingSession, amounts[i], whos[i]);
|
(globalIndex, currentWeavingSession) = _insertWithAssert(amounts[i], whos[i]);
|
||||||
assertTrue(_verifyProof(globalIndex, currentWeavingSession, block.number, amounts[i], whos[i]));
|
assertTrue(_verifyProof(globalIndex, currentWeavingSession, block.number, amounts[i], whos[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
globalIndex = _insertWithAssert(currentWeavingSession, amounts[69], whos[69]);
|
(globalIndex, newWeavingSession) = _insertWithAssert(amounts[69], whos[69]);
|
||||||
uint256 newSession = gatekeeper.currentWeavingSession();
|
assertEq(currentWeavingSession + 1, newWeavingSession);
|
||||||
|
|
||||||
assertEq(currentWeavingSession + 1, newSession);
|
|
||||||
vm.roll(block.number + 1337);
|
vm.roll(block.number + 1337);
|
||||||
|
|
||||||
assertTrue(_verifyProof(globalIndex, newSession, block.number, amounts[69], whos[69]));
|
assertTrue(_verifyProof(globalIndex, newWeavingSession, block.number, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(0, currentWeavingSession, block.number, amounts[0], whos[0]));
|
assertTrue(_verifyProof(0, currentWeavingSession, block.number, amounts[0], whos[0]));
|
||||||
assertTrue(_verifyProof(69, currentWeavingSession, block.number, amounts[69], whos[69]));
|
assertTrue(_verifyProof(69, currentWeavingSession, block.number, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(420, currentWeavingSession, block.number, amounts[420], whos[420]));
|
assertTrue(_verifyProof(420, currentWeavingSession, block.number, amounts[420], whos[420]));
|
||||||
@ -156,7 +156,7 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
assertTrue(_verifyProof(69, currentWeavingSession, 100, amounts[69], whos[69]));
|
assertTrue(_verifyProof(69, currentWeavingSession, 100, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(420, currentWeavingSession, 100, amounts[420], whos[420]));
|
assertTrue(_verifyProof(420, currentWeavingSession, 100, amounts[420], whos[420]));
|
||||||
|
|
||||||
assertFalse(_verifyProof(globalIndex, newSession, 100, amounts[69], whos[69]));
|
assertFalse(_verifyProof(globalIndex, newWeavingSession, 100, amounts[69], whos[69]));
|
||||||
assertFalse(_verifyProof(1337, currentWeavingSession, 100, amounts[1337], whos[1337]));
|
assertFalse(_verifyProof(1337, currentWeavingSession, 100, amounts[1337], whos[1337]));
|
||||||
assertFalse(_verifyProof(2047, currentWeavingSession, 100, amounts[2047], whos[2047]));
|
assertFalse(_verifyProof(2047, currentWeavingSession, 100, amounts[2047], whos[2047]));
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
staking.ghost(whos[i], amounts[i]);
|
staking.ghost(whos[i], amounts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(_verifyProof(globalIndex, newSession, block.number, amounts[69], whos[69]));
|
assertTrue(_verifyProof(globalIndex, newWeavingSession, block.number, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(0, currentWeavingSession, block.number, amounts[0], whos[0]));
|
assertTrue(_verifyProof(0, currentWeavingSession, block.number, amounts[0], whos[0]));
|
||||||
assertTrue(_verifyProof(69, currentWeavingSession, block.number, amounts[69], whos[69]));
|
assertTrue(_verifyProof(69, currentWeavingSession, block.number, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(420, currentWeavingSession, block.number, amounts[420], whos[420]));
|
assertTrue(_verifyProof(420, currentWeavingSession, block.number, amounts[420], whos[420]));
|
||||||
@ -185,7 +185,7 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
assertTrue(_verifyProof(69, currentWeavingSession, 100, amounts[69], whos[69]));
|
assertTrue(_verifyProof(69, currentWeavingSession, 100, amounts[69], whos[69]));
|
||||||
assertTrue(_verifyProof(420, currentWeavingSession, 100, amounts[420], whos[420]));
|
assertTrue(_verifyProof(420, currentWeavingSession, 100, amounts[420], whos[420]));
|
||||||
|
|
||||||
assertFalse(_verifyProof(globalIndex, newSession, 100, amounts[69], whos[69]));
|
assertFalse(_verifyProof(globalIndex, newWeavingSession, 100, amounts[69], whos[69]));
|
||||||
assertFalse(_verifyProof(1337, currentWeavingSession, 100, amounts[1337], whos[1337]));
|
assertFalse(_verifyProof(1337, currentWeavingSession, 100, amounts[1337], whos[1337]));
|
||||||
assertFalse(_verifyProof(2047, currentWeavingSession, 100, amounts[2047], whos[2047]));
|
assertFalse(_verifyProof(2047, currentWeavingSession, 100, amounts[2047], whos[2047]));
|
||||||
|
|
||||||
@ -212,41 +212,43 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _insertWithAssert(
|
function _insertWithAssert(
|
||||||
uint256 session,
|
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
bytes32 who
|
bytes32 who
|
||||||
) private returns (uint256 globalIndex) {
|
) private returns (uint256 globalIndex, uint256 emittedSession) {
|
||||||
uint256 targetSlot = gatekeeper.filledEntries(session);
|
uint256 preSession = gatekeeper.currentWeavingSession();
|
||||||
bytes32 previousHash = gatekeeper.treeNodesLatest(session, targetSlot);
|
|
||||||
uint256 prevEntries = gatekeeper.filledEntries(session);
|
uint256 targetSlot = gatekeeper.filledEntries(preSession);
|
||||||
uint160 prevLength = gatekeeper.slotLengths(session, targetSlot);
|
bytes32 previousHash = gatekeeper.treeNodesLatest(preSession, targetSlot);
|
||||||
|
uint256 prevEntries = gatekeeper.filledEntries(preSession);
|
||||||
|
uint160 prevLength = gatekeeper.slotLengths(preSession, targetSlot);
|
||||||
|
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
globalIndex = staking.ghost(who, amount);
|
staking.ghost(who, amount);
|
||||||
|
(globalIndex, emittedSession) = _getInsertedDataFromLogs();
|
||||||
|
|
||||||
|
if (preSession != emittedSession) {
|
||||||
|
assertEq(preSession + 1, emittedSession);
|
||||||
|
assertEq(emittedSession, gatekeeper.currentWeavingSession());
|
||||||
|
|
||||||
if (session + 1 == gatekeeper.currentWeavingSession()) {
|
|
||||||
assertEq(prevLength, gatekeeper.DEPTH());
|
assertEq(prevLength, gatekeeper.DEPTH());
|
||||||
assertEq(gatekeeper.slotLengths(session + 1, 0), 1);
|
assertEq(gatekeeper.slotLengths(emittedSession, 0), 1);
|
||||||
assertEq(prevEntries, gatekeeper.ENTRIES());
|
assertEq(prevEntries, gatekeeper.ENTRIES());
|
||||||
assertEq(gatekeeper.filledEntries(session + 1), 1);
|
assertEq(gatekeeper.filledEntries(emittedSession), 1);
|
||||||
assertEq(session + 1, gatekeeper.currentWeavingSession());
|
|
||||||
|
|
||||||
session += 1;
|
|
||||||
previousHash = bytes32(0);
|
previousHash = bytes32(0);
|
||||||
prevLength = gatekeeper.slotLengths(session, 0);
|
|
||||||
} else {
|
} else {
|
||||||
assertEq(prevLength + 1, gatekeeper.slotLengths(session, targetSlot));
|
assertEq(prevLength + 1, gatekeeper.slotLengths(emittedSession, targetSlot));
|
||||||
assertEq(prevEntries + 1, gatekeeper.filledEntries(session));
|
assertEq(prevEntries + 1, gatekeeper.filledEntries(emittedSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
bytes32 preimage1 = gatekeeper.slotValues(session, globalIndex);
|
bytes32 preimage1 = gatekeeper.slotValues(emittedSession, globalIndex);
|
||||||
bytes32 preimage2 = gatekeeper.computePreimage(globalIndex, amount, who);
|
bytes32 preimage2 = gatekeeper.computePreimage(globalIndex, amount, who);
|
||||||
assertEq(preimage1, preimage2);
|
assertEq(preimage1, preimage2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
bytes32 nodeHash1 = gatekeeper.treeNodesLatest(session, globalIndex);
|
bytes32 nodeHash1 = gatekeeper.treeNodesLatest(emittedSession, globalIndex);
|
||||||
bytes32 preimageHash = Hashes.efficientKeccak256(
|
bytes32 preimageHash = Hashes.efficientKeccak256(
|
||||||
gatekeeper.computePreimage(globalIndex, amount, who)
|
gatekeeper.computePreimage(globalIndex, amount, who)
|
||||||
);
|
);
|
||||||
@ -268,4 +270,17 @@ contract GatekeeperWeaverTest is Test {
|
|||||||
|
|
||||||
return (whos, amounts);
|
return (whos, amounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _getInsertedDataFromLogs() private returns (uint256 index, uint256 session) {
|
||||||
|
Vm.Log[] memory entries = vm.getRecordedLogs();
|
||||||
|
bytes32 targetTopic = keccak256("ThreadInserted(uint256,uint256)");
|
||||||
|
|
||||||
|
for (uint256 i = entries.length; i > 0; i--) {
|
||||||
|
if (entries[i - 1].topics.length > 0 && entries[i - 1].topics[0] == targetTopic) {
|
||||||
|
(index, session) = abi.decode(entries[i - 1].data, (uint256, uint256));
|
||||||
|
return (index, session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
revert("Target event not found in logs");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,7 +86,6 @@ contract StakingTest is Test {
|
|||||||
|
|
||||||
event DistributorSet(address distributor);
|
event DistributorSet(address distributor);
|
||||||
event WarmupSet(uint256 warmup);
|
event WarmupSet(uint256 warmup);
|
||||||
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
vm.startPrank(INITIALIZER);
|
vm.startPrank(INITIALIZER);
|
||||||
@ -640,23 +639,6 @@ contract StakingTest is Test {
|
|||||||
assertEq(ghst.totalSupply(), 0);
|
assertEq(ghst.totalSupply(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_ghostTokensEmitsEvent() public {
|
|
||||||
_prepareAndRoll(ALICE, BIG_AMOUNT, true, true);
|
|
||||||
uint256 aliceBalance = stnk.balanceOf(ALICE);
|
|
||||||
|
|
||||||
vm.startPrank(ALICE);
|
|
||||||
stnk.approve(address(staking), aliceBalance);
|
|
||||||
uint256 ghstBalance = staking.wrap(ALICE, aliceBalance);
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
|
||||||
vm.expectEmit(true, true, true, false, staking.gatekeeper());
|
|
||||||
emit Ghosted(receiver, ghstBalance);
|
|
||||||
|
|
||||||
vm.prank(ALICE);
|
|
||||||
staking.ghost(receiver, ghstBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_breakoutLogicWorks() public {
|
function test_breakoutLogicWorks() public {
|
||||||
uint256 initialIndex = staking.index();
|
uint256 initialIndex = staking.index();
|
||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
||||||
@ -678,9 +660,6 @@ contract StakingTest is Test {
|
|||||||
uint256 range = (payout * 3) / 100;
|
uint256 range = (payout * 3) / 100;
|
||||||
requestedPayout = (pseudoRandom % range) + 1;
|
requestedPayout = (pseudoRandom % range) + 1;
|
||||||
|
|
||||||
vm.expectEmit(true, true, true, false, staking.gatekeeper());
|
|
||||||
emit Ghosted(receiver, requestedPayout);
|
|
||||||
|
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
staking.breakout(receiver, requestedPayout);
|
staking.breakout(receiver, requestedPayout);
|
||||||
expectedPayout += requestedPayout;
|
expectedPayout += requestedPayout;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user