tests added for buyback logic based on the real signatures
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
f71ae5aebe
commit
a752977447
@ -3,34 +3,76 @@ pragma solidity 0.8.20;
|
|||||||
import {Test} from "forge-std/Test.sol";
|
import {Test} from "forge-std/Test.sol";
|
||||||
|
|
||||||
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
||||||
|
import {FullMath} from "../../src/libraries/FullMath.sol";
|
||||||
|
import {RequestPacking} from "../../src/libraries/Packing.sol";
|
||||||
|
import {IStorageHistory} from "../../src/interfaces/IStorageHistory.sol";
|
||||||
|
|
||||||
|
contract MockStaking is Test {
|
||||||
|
Gatekeeper public gatekeeper;
|
||||||
|
|
||||||
|
mapping(address => uint256) private _materializedAmounts;
|
||||||
|
|
||||||
|
constructor(uint256 existential) {
|
||||||
|
gatekeeper = new Gatekeeper(existential, address(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function runGhost(bytes32 receiver, uint256 amount) external {
|
||||||
|
gatekeeper.ghost(receiver, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runMaterialize(
|
||||||
|
uint256 exodusSession,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 packed,
|
||||||
|
address caller
|
||||||
|
) external payable {
|
||||||
|
if (msg.value > 0) {
|
||||||
|
vm.deal(address(gatekeeper), address(gatekeeper).balance + msg.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.prank(address(gatekeeper), caller);
|
||||||
|
gatekeeper.materialize{value: msg.value}(exodusSession, amount, packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function materialize(address receiver, uint256 amount) external {
|
||||||
|
_materializedAmounts[receiver] += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function materializedAmount(address who) external view returns (uint256) {
|
||||||
|
return _materializedAmounts[who];
|
||||||
|
}
|
||||||
|
|
||||||
|
function totalReserves() external pure returns (uint256) {
|
||||||
|
return type(uint256).max;
|
||||||
|
}
|
||||||
|
|
||||||
|
function baseSupply() external pure returns (uint256) {
|
||||||
|
return type(uint256).max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contract GatekeeperTest is Test {
|
contract GatekeeperTest is Test {
|
||||||
|
using RequestPacking for RequestPacking.RequestPayload;
|
||||||
|
|
||||||
address constant ALICE = 0x0000000000000000000000000000000000000001;
|
address constant ALICE = 0x0000000000000000000000000000000000000001;
|
||||||
address constant BOB = 0x0000000000000000000000000000000000000002;
|
address constant BOB = 0x0000000000000000000000000000000000000002;
|
||||||
uint256 constant EXISTENTIAL = 1337;
|
uint256 constant EXISTENTIAL = 1337;
|
||||||
uint256 constant INIT_AMOUNT = 69 * 1e18;
|
uint256 constant INIT_AMOUNT = 69 * 1e18;
|
||||||
|
|
||||||
Gatekeeper gatekeeper;
|
Gatekeeper gatekeeper;
|
||||||
|
MockStaking staking;
|
||||||
|
|
||||||
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
event Ghosted(bytes32 indexed receiver, uint256 indexed amount);
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
vm.prank(ALICE, ALICE);
|
vm.prank(ALICE, ALICE);
|
||||||
gatekeeper = new Gatekeeper(EXISTENTIAL, address(0));
|
staking = new MockStaking(EXISTENTIAL);
|
||||||
|
gatekeeper = staking.gatekeeper();
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_correctInitialization() public {
|
function test_correctInitialization() public view {
|
||||||
assertEq(gatekeeper.staking(), ALICE);
|
assertEq(gatekeeper.staking(), address(staking));
|
||||||
assertEq(gatekeeper.ghostedSupply(), 0);
|
assertEq(gatekeeper.ghostedSupply(), 0);
|
||||||
|
|
||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
|
||||||
vm.prank(ALICE);
|
|
||||||
gatekeeper.ghost(receiver, INIT_AMOUNT);
|
|
||||||
|
|
||||||
vm.prank(BOB);
|
|
||||||
Gatekeeper anotherGatekeeper = new Gatekeeper(EXISTENTIAL, address(gatekeeper));
|
|
||||||
assertEq(anotherGatekeeper.staking(), ALICE);
|
|
||||||
assertEq(anotherGatekeeper.ghostedSupply(), INIT_AMOUNT);
|
|
||||||
assertEq(anotherGatekeeper.existentialDeposit(), EXISTENTIAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_ghostTokensWork(uint256 ghostAmount) public {
|
function test_ghostTokensWork(uint256 ghostAmount) public {
|
||||||
@ -39,7 +81,7 @@ contract GatekeeperTest is Test {
|
|||||||
uint256 ghostedSupply = gatekeeper.ghostedSupply();
|
uint256 ghostedSupply = gatekeeper.ghostedSupply();
|
||||||
|
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
gatekeeper.ghost(receiver, ghostAmount);
|
staking.runGhost(receiver, ghostAmount);
|
||||||
assertEq(gatekeeper.ghostedSupply(), ghostedSupply + ghostAmount);
|
assertEq(gatekeeper.ghostedSupply(), ghostedSupply + ghostAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +91,7 @@ contract GatekeeperTest is Test {
|
|||||||
|
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
vm.prank(someone);
|
vm.prank(someone);
|
||||||
gatekeeper.ghost(receiver, 69);
|
staking.runGhost(receiver, 69);
|
||||||
assertEq(gatekeeper.ghostedSupply(), 0);
|
assertEq(gatekeeper.ghostedSupply(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,14 +102,40 @@ contract GatekeeperTest is Test {
|
|||||||
vm.expectEmit(true, true, true, false, address(gatekeeper));
|
vm.expectEmit(true, true, true, false, address(gatekeeper));
|
||||||
emit Ghosted(receiver, ghostAmount);
|
emit Ghosted(receiver, ghostAmount);
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
gatekeeper.ghost(receiver, ghostAmount);
|
staking.runGhost(receiver, ghostAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: revisit with actual signatures from the cargo test
|
function test_materializeWork(uint256 exodusSession, uint256 bobAmount, uint32 bobCommission) public {
|
||||||
// function test_materializeWork(uint256 ghostAmount) public {
|
vm.assume(bobAmount > 1337 && bobAmount < 1_000 ether);
|
||||||
// vm.prank(ALICE);
|
vm.assume(bobCommission > 0 && bobCommission <= type(uint32).max);
|
||||||
// gatekeeper.materialize(0, ghostAmount, 0, ALICE);
|
|
||||||
// }
|
address storageHistory = gatekeeper.storageHistory();
|
||||||
|
uint256 commissionAmount = FullMath.mulDiv(bobAmount, uint256(bobCommission), type(uint32).max);
|
||||||
|
uint256 bobPacked = RequestPacking.pack(uint32(bobCommission), uint64(block.chainid), BOB);
|
||||||
|
|
||||||
|
vm.prank(ALICE);
|
||||||
|
staking.runGhost(bytes32(abi.encodePacked(ALICE)), bobAmount);
|
||||||
|
|
||||||
|
uint256 nativeNeeded = FullMath.mulDiv(commissionAmount, staking.totalReserves(), staking.baseSupply());
|
||||||
|
|
||||||
|
vm.deal(ALICE, nativeNeeded + 1 ether);
|
||||||
|
assertEq(BOB.balance, 0 ether);
|
||||||
|
uint256 aliceStartingNative = ALICE.balance;
|
||||||
|
|
||||||
|
uint256 previousAliceAmount = staking.materializedAmount(ALICE);
|
||||||
|
uint256 previousBobAmount = staking.materializedAmount(BOB);
|
||||||
|
|
||||||
|
vm.prank(ALICE);
|
||||||
|
staking.runMaterialize{value: nativeNeeded}(exodusSession, bobAmount, bobPacked, ALICE);
|
||||||
|
|
||||||
|
assertApproxEqAbs(previousAliceAmount + commissionAmount, staking.materializedAmount(ALICE), 1000);
|
||||||
|
assertApproxEqAbs(previousBobAmount + (bobAmount - commissionAmount), staking.materializedAmount(BOB), 1000);
|
||||||
|
|
||||||
|
assertEq(BOB.balance, nativeNeeded);
|
||||||
|
assertEq(ALICE.balance, aliceStartingNative - nativeNeeded);
|
||||||
|
|
||||||
|
assert(IStorageHistory(storageHistory).isTransactionExecuted(exodusSession));
|
||||||
|
}
|
||||||
|
|
||||||
function test_rotateWork(bytes32 aggregatedPublicKey) public {
|
function test_rotateWork(bytes32 aggregatedPublicKey) public {
|
||||||
vm.warp(block.timestamp + 1);
|
vm.warp(block.timestamp + 1);
|
||||||
@ -81,18 +149,24 @@ contract GatekeeperTest is Test {
|
|||||||
|
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
gatekeeper.ghost(receiver, amount);
|
staking.runGhost(receiver, amount);
|
||||||
|
|
||||||
assertEq(gatekeeper.ghostedSupply(), 0);
|
assertEq(gatekeeper.ghostedSupply(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_signatureVerificationsWorks() public {
|
function test_signatureVerificationsWorks() public {
|
||||||
assertEq(gatekeeper.deployer(), ALICE);
|
assertEq(gatekeeper.deployer(), ALICE);
|
||||||
|
|
||||||
|
vm.prank(ALICE);
|
||||||
|
staking.runGhost(bytes32(abi.encodePacked(ALICE)), type(uint104).max);
|
||||||
|
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
gatekeeper.updatePublicKeyMetadata(0, 0x875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e4669, 0);
|
gatekeeper.updatePublicKeyMetadata(0, 0x875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e4669, 0);
|
||||||
|
|
||||||
(bytes32 prevPublicKey, uint8 prevParity, uint64 prevSession) = gatekeeper.latestPublicKeyInfo();
|
(bytes32 prevPublicKey, uint8 prevParity,) = gatekeeper.latestPublicKeyInfo();
|
||||||
|
|
||||||
|
// genesis validators 4 validators, DKG #0
|
||||||
|
// exodus session #0
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a670000000000000000000000000000000000000000000000000000000000000000875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e46690000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a670000000000000000000000000000000000000000000000000000000000000000875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e46690000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"044d9fa18df9da04381ed256981570a6ef6a0893496ded966fc994662df931ed423b29e2737394b31d8498594caad7b77e36ab31ac79df3796a1b6f26baa5552ae",
|
hex"044d9fa18df9da04381ed256981570a6ef6a0893496ded966fc994662df931ed423b29e2737394b31d8498594caad7b77e36ab31ac79df3796a1b6f26baa5552ae",
|
||||||
@ -102,41 +176,46 @@ contract GatekeeperTest is Test {
|
|||||||
(bytes32 publicKey, uint8 parity, uint64 session) = gatekeeper.latestPublicKeyInfo();
|
(bytes32 publicKey, uint8 parity, uint64 session) = gatekeeper.latestPublicKeyInfo();
|
||||||
assertEq(publicKey, prevPublicKey);
|
assertEq(publicKey, prevPublicKey);
|
||||||
assertEq(parity, prevParity);
|
assertEq(parity, prevParity);
|
||||||
assertEq(session, prevSession);
|
assertEq(session, 0);
|
||||||
|
|
||||||
|
// could not apply signature from DKG #2
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000023492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000043492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"042b45a8909a137e7bab5caf4b2870ece0469c6a4149c10074cfdaf2c114a65daefe14179830c95d07fea439ce78d2ad11898578e5e678dbcb98a7576da9e57c77",
|
hex"0496bacdcc4260a610c9ef465cc1d9f973dda7d4794a65c1d1ea8ea2bb8aa3ddb08d171f5aa267c1ddc64343b4f054424af0c61b57e1f359cd4e23876a0fa4a704",
|
||||||
0x5a61b59cededac4010b89bc6935e0cb7d975f5e2db457227ee473203de5247ed
|
0x34383aacbe014a6fed8b5976ccfcdcbb93cef7e41a6634f934432d9ede912c14
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// genesis validators 7 validators, DKG #1
|
||||||
|
// exodus session #2
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000014e8c1fe96d6737cdabbcc96501d6656b9d0b659b3a528ef507f2d52bef29e1570000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000024e8c1fe96d6737cdabbcc96501d6656b9d0b659b3a528ef507f2d52bef29e1570000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"04d4c4daeb68bf8e40db4b516ddf3be9dd0f56a81809945e30bf06b7e5b26d1b27c83367de842f00c915f06ab1755dc511a3a3fe213308b5e65c6832d9d9bb3b38",
|
hex"04460e7dce1ebd4cc7527ba80852b6fcdbf8810da3b2173c2f3b3da63206a44407f79d5b5b4c3adcdcce2404c7488240873babb856f065fa551caa6dddea68ca06",
|
||||||
0xd93d1b1613277ddb27df66bdea16d7b91adf975eb150e27a872ce035655ec13d
|
0x7f6ac70e1e3f3ddd7101a439e7da6f8622a0c8cc38ce42ce81d911d8ad23af90
|
||||||
);
|
);
|
||||||
|
|
||||||
(publicKey, parity, session) = gatekeeper.latestPublicKeyInfo();
|
(publicKey, parity, session) = gatekeeper.latestPublicKeyInfo();
|
||||||
assert(publicKey != prevPublicKey);
|
assert(publicKey != prevPublicKey);
|
||||||
assertEq(parity, prevParity);
|
assertEq(parity, prevParity);
|
||||||
assertEq(session, prevSession + 1);
|
assertEq(session, 2);
|
||||||
|
|
||||||
prevPublicKey = publicKey;
|
prevPublicKey = publicKey;
|
||||||
prevParity = parity;
|
prevParity = parity;
|
||||||
prevSession = session;
|
|
||||||
|
|
||||||
|
// genesis validators 5 validators, DKG #2
|
||||||
|
// exodus session #4
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000023492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000043492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"042b45a8909a137e7bab5caf4b2870ece0469c6a4149c10074cfdaf2c114a65daefe14179830c95d07fea439ce78d2ad11898578e5e678dbcb98a7576da9e57c77",
|
hex"0496bacdcc4260a610c9ef465cc1d9f973dda7d4794a65c1d1ea8ea2bb8aa3ddb08d171f5aa267c1ddc64343b4f054424af0c61b57e1f359cd4e23876a0fa4a704",
|
||||||
0x5a61b59cededac4010b89bc6935e0cb7d975f5e2db457227ee473203de5247ed
|
0x34383aacbe014a6fed8b5976ccfcdcbb93cef7e41a6634f934432d9ede912c14
|
||||||
);
|
);
|
||||||
|
|
||||||
(publicKey, parity, session) = gatekeeper.latestPublicKeyInfo();
|
(publicKey, parity, session) = gatekeeper.latestPublicKeyInfo();
|
||||||
assert(publicKey != prevPublicKey);
|
assert(publicKey != prevPublicKey);
|
||||||
assertEq(parity, prevParity);
|
assertEq(parity, prevParity);
|
||||||
assertEq(session, prevSession + 1);
|
assertEq(session, 4);
|
||||||
|
|
||||||
|
// could not apply DKG #0 no more
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a670000000000000000000000000000000000000000000000000000000000000000875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e46690000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a670000000000000000000000000000000000000000000000000000000000000000875cdcba4ae5494518fa2602791e667ca0998402b6a69e5b7cb4c72dba4e46690000000000000000000000000000000000000000000000000000000000000000",
|
||||||
@ -144,18 +223,63 @@ contract GatekeeperTest is Test {
|
|||||||
0x24029a571fcaeadd14f4afe8be62afe3d07876ae270c3caf446ecb6cfc7c08f2
|
0x24029a571fcaeadd14f4afe8be62afe3d07876ae270c3caf446ecb6cfc7c08f2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// could not apply DKG #1 no more
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000014e8c1fe96d6737cdabbcc96501d6656b9d0b659b3a528ef507f2d52bef29e1570000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000024e8c1fe96d6737cdabbcc96501d6656b9d0b659b3a528ef507f2d52bef29e1570000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"04d4c4daeb68bf8e40db4b516ddf3be9dd0f56a81809945e30bf06b7e5b26d1b27c83367de842f00c915f06ab1755dc511a3a3fe213308b5e65c6832d9d9bb3b38",
|
hex"04460e7dce1ebd4cc7527ba80852b6fcdbf8810da3b2173c2f3b3da63206a44407f79d5b5b4c3adcdcce2404c7488240873babb856f065fa551caa6dddea68ca06",
|
||||||
0xd93d1b1613277ddb27df66bdea16d7b91adf975eb150e27a872ce035655ec13d
|
0x7f6ac70e1e3f3ddd7101a439e7da6f8622a0c8cc38ce42ce81d911d8ad23af90
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// could not apply DKG #2 no more
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
gatekeeper.verify(
|
gatekeeper.verify(
|
||||||
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000023492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
hex"49f03a6700000000000000000000000000000000000000000000000000000000000000043492bc8bb10848f1f788496ccadde7d458eac4ac2c1eca2dd2c7a506d8fa2c5b0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
hex"042b45a8909a137e7bab5caf4b2870ece0469c6a4149c10074cfdaf2c114a65daefe14179830c95d07fea439ce78d2ad11898578e5e678dbcb98a7576da9e57c77",
|
hex"0496bacdcc4260a610c9ef465cc1d9f973dda7d4794a65c1d1ea8ea2bb8aa3ddb08d171f5aa267c1ddc64343b4f054424af0c61b57e1f359cd4e23876a0fa4a704",
|
||||||
0x5a61b59cededac4010b89bc6935e0cb7d975f5e2db457227ee473203de5247ed
|
0x34383aacbe014a6fed8b5976ccfcdcbb93cef7e41a6634f934432d9ede912c14
|
||||||
);
|
);
|
||||||
|
|
||||||
|
uint256 aliceAmountBefore = staking.materializedAmount(ALICE);
|
||||||
|
uint256 bobAmountBefore = staking.materializedAmount(BOB);
|
||||||
|
uint256 aliceBalanceBefore = ALICE.balance;
|
||||||
|
uint256 bobBalanceBefore = BOB.balance;
|
||||||
|
|
||||||
|
// execute bridge out, happened on DKG #0
|
||||||
|
// amount: 69; commission: 0%; ALICE
|
||||||
|
// exodus session #1
|
||||||
|
gatekeeper.verify(
|
||||||
|
hex"39cd99050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000010000000000007a6900000000",
|
||||||
|
hex"04bf0bcb3d42d8187c543a82ee201a221525047020ff0ac03e4d60e322d3eb6d8ab5bfdae43ea0fbf59128d201b8076727c3c63fe8a5c2b890fdb3c97a7da5f207",
|
||||||
|
0x08f121a1615782c83cce41d7fc2064be57fdeeae8b45f716211b3c8c873f3e4c
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEq(aliceAmountBefore + 69, staking.materializedAmount(ALICE));
|
||||||
|
assertEq(bobAmountBefore, staking.materializedAmount(BOB));
|
||||||
|
assertEq(aliceBalanceBefore, ALICE.balance);
|
||||||
|
assertEq(bobBalanceBefore, BOB.balance);
|
||||||
|
|
||||||
|
vm.deal(ALICE, 220);
|
||||||
|
|
||||||
|
aliceAmountBefore = staking.materializedAmount(ALICE);
|
||||||
|
bobAmountBefore = staking.materializedAmount(BOB);
|
||||||
|
aliceBalanceBefore = ALICE.balance;
|
||||||
|
bobBalanceBefore = BOB.balance;
|
||||||
|
|
||||||
|
uint256 buyback = 220;
|
||||||
|
|
||||||
|
// execute bridge out, happened on DKG #1
|
||||||
|
// amount: 420; commission: 50%; BOB
|
||||||
|
// exodus session #3
|
||||||
|
vm.prank(ALICE, ALICE);
|
||||||
|
gatekeeper.verify{value: buyback}(
|
||||||
|
hex"39cd9905000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000020000000000007a6980000000",
|
||||||
|
hex"04089940ed9bb8d7f3a77adfafb0d5ebc45af558ade46844856c049aa912b9d8401826e17f24c0aa625524ff4a65b430a19422b4f9754cec3b862641f17f99b1a9",
|
||||||
|
0x9d2cf40ab0b1820858fe6f8950e2f511b4acb57b00b37bb93760978e2add4243
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEq(aliceAmountBefore + 210, staking.materializedAmount(ALICE));
|
||||||
|
assertEq(bobAmountBefore + 210, staking.materializedAmount(BOB));
|
||||||
|
assertEq(aliceBalanceBefore - buyback, ALICE.balance);
|
||||||
|
assertEq(bobBalanceBefore + buyback, BOB.balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,19 +4,56 @@ import {Test} from "forge-std/Test.sol";
|
|||||||
|
|
||||||
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
import {Gatekeeper} from "../../src/Gatekeeper.sol";
|
||||||
import {IStorageHistory} from "../../src/interfaces/IStorageHistory.sol";
|
import {IStorageHistory} from "../../src/interfaces/IStorageHistory.sol";
|
||||||
|
import {RequestPacking} from "../../src/libraries/Packing.sol";
|
||||||
|
|
||||||
|
contract MockStaking is Test {
|
||||||
|
Gatekeeper public gatekeeper;
|
||||||
|
|
||||||
|
mapping(address => uint256) private _materializedAmounts;
|
||||||
|
|
||||||
|
constructor(uint256 existential) {
|
||||||
|
gatekeeper = new Gatekeeper(existential, address(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function redoGatekeeper(uint256 existential) external {
|
||||||
|
gatekeeper = new Gatekeeper(existential, address(gatekeeper));
|
||||||
|
}
|
||||||
|
|
||||||
|
function runGhost(bytes32 receiver, uint256 amount) external {
|
||||||
|
gatekeeper.ghost(receiver, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runMaterialize(uint256 exodusSession, uint256 amount, uint256 packed) external {
|
||||||
|
vm.prank(address(gatekeeper));
|
||||||
|
gatekeeper.materialize(exodusSession, amount, packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function materialize(address receiver, uint256 amount) external {
|
||||||
|
_materializedAmounts[receiver] += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function materializedAmount(address who) external view returns (uint256) {
|
||||||
|
return _materializedAmounts[who];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contract GatekeeperStorageHistoryTest is Test {
|
contract GatekeeperStorageHistoryTest is Test {
|
||||||
|
using RequestPacking for RequestPacking.RequestPayload;
|
||||||
|
|
||||||
address constant ALICE = 0x0000000000000000000000000000000000000001;
|
address constant ALICE = 0x0000000000000000000000000000000000000001;
|
||||||
address constant BOB = 0x0000000000000000000000000000000000000002;
|
address constant BOB = 0x0000000000000000000000000000000000000002;
|
||||||
uint256 constant INIT_AMOUNT = 69 * 1e18;
|
uint256 constant INIT_AMOUNT = 1337 * 1e18;
|
||||||
uint256 constant INIT_GHOSTED = type(uint104).max / 2;
|
|
||||||
uint256 constant EXISTENTIAL = 0;
|
uint256 constant EXISTENTIAL = 0;
|
||||||
|
|
||||||
Gatekeeper gatekeeper;
|
Gatekeeper gatekeeper;
|
||||||
|
MockStaking staking;
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
vm.prank(ALICE);
|
vm.prank(ALICE);
|
||||||
gatekeeper = new Gatekeeper(EXISTENTIAL, address(0));
|
staking = new MockStaking(EXISTENTIAL);
|
||||||
|
|
||||||
|
staking.runGhost(bytes32(abi.encodePacked(ALICE)), INIT_AMOUNT);
|
||||||
|
gatekeeper = staking.gatekeeper();
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_correctStorageHistoryInitialization() public view {
|
function test_correctStorageHistoryInitialization() public view {
|
||||||
@ -24,13 +61,16 @@ contract GatekeeperStorageHistoryTest is Test {
|
|||||||
IStorageHistory.DeploymentSnapshot memory snapshot = IStorageHistory(storageHistory).deploymentSnapshot();
|
IStorageHistory.DeploymentSnapshot memory snapshot = IStorageHistory(storageHistory).deploymentSnapshot();
|
||||||
|
|
||||||
assertEq(snapshot.deployedAt, 0);
|
assertEq(snapshot.deployedAt, 0);
|
||||||
assertEq(snapshot.amountIn, 0);
|
assertEq(snapshot.amountIn, INIT_AMOUNT);
|
||||||
assertEq(snapshot.amountOut, 0);
|
assertEq(snapshot.amountOut, 0);
|
||||||
assertEq(gatekeeper.ghostedSupply(), 0);
|
assertEq(gatekeeper.ghostedSupply(), INIT_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_historicalAmountsOnlyIncrease(uint256 ghostAmount) public {
|
function test_historicalAmountsOnlyIncrease(uint256 ghostAmount, uint64 exodusSession) public {
|
||||||
vm.assume(ghostAmount > 0 && ghostAmount < INIT_GHOSTED / 2);
|
vm.assume(ghostAmount > 0 && ghostAmount < INIT_AMOUNT);
|
||||||
|
|
||||||
|
uint256 amountToGhost = ghostAmount;
|
||||||
|
uint256 amountToMaterialize = ghostAmount / 2;
|
||||||
|
|
||||||
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
bytes32 receiver = bytes32(abi.encodePacked(ALICE));
|
||||||
address storageHistory = gatekeeper.storageHistory();
|
address storageHistory = gatekeeper.storageHistory();
|
||||||
@ -40,17 +80,19 @@ contract GatekeeperStorageHistoryTest is Test {
|
|||||||
uint104 amountOut = snapshot.amountOut;
|
uint104 amountOut = snapshot.amountOut;
|
||||||
|
|
||||||
if (ghostAmount % 2 == 0) {
|
if (ghostAmount % 2 == 0) {
|
||||||
vm.prank(ALICE);
|
staking.runGhost(receiver, amountToGhost);
|
||||||
gatekeeper.ghost(receiver, ghostAmount);
|
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
amountIn += uint104(ghostAmount);
|
amountIn += uint104(amountToGhost);
|
||||||
} else {
|
} else {
|
||||||
if (IStorageHistory(storageHistory).bridgeImbalance() >= ghostAmount) {
|
|
||||||
vm.prank(ALICE);
|
|
||||||
gatekeeper.materialize(0, ghostAmount, 0, BOB);
|
|
||||||
// forge-lint: disable-next-line(unsafe-typecast)
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
amountOut += uint104(ghostAmount);
|
uint256 packed = RequestPacking.pack(0, uint64(block.chainid), BOB);
|
||||||
}
|
uint256 previousAmount = staking.materializedAmount(BOB);
|
||||||
|
|
||||||
|
staking.runMaterialize(exodusSession, amountToMaterialize, packed);
|
||||||
|
assertEq(previousAmount + amountToMaterialize, staking.materializedAmount(BOB));
|
||||||
|
|
||||||
|
// forge-lint: disable-next-line(unsafe-typecast)
|
||||||
|
amountOut += uint104(amountToMaterialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
IStorageHistory.DeploymentSnapshot memory newSnapshot = IStorageHistory(storageHistory).deploymentSnapshot();
|
IStorageHistory.DeploymentSnapshot memory newSnapshot = IStorageHistory(storageHistory).deploymentSnapshot();
|
||||||
@ -59,4 +101,29 @@ contract GatekeeperStorageHistoryTest is Test {
|
|||||||
assertEq(gatekeeper.ghostedSupply(), amountIn - amountOut);
|
assertEq(gatekeeper.ghostedSupply(), amountIn - amountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_inheritanceWorksForHistoricalStorge() public {
|
||||||
|
uint256 exodusSession = 69;
|
||||||
|
uint256 packed = RequestPacking.pack(0, uint64(block.chainid), BOB);
|
||||||
|
staking.runMaterialize(exodusSession, INIT_AMOUNT, packed);
|
||||||
|
staking.runGhost(bytes32(abi.encodePacked(ALICE)), INIT_AMOUNT);
|
||||||
|
|
||||||
|
address prevStorageHistory = gatekeeper.storageHistory();
|
||||||
|
IStorageHistory.DeploymentSnapshot memory prevSnapshot = IStorageHistory(prevStorageHistory).deploymentSnapshot();
|
||||||
|
|
||||||
|
staking.redoGatekeeper(EXISTENTIAL + 1);
|
||||||
|
assert(gatekeeper != staking.gatekeeper());
|
||||||
|
|
||||||
|
address currStorageHistory = gatekeeper.storageHistory();
|
||||||
|
IStorageHistory.DeploymentSnapshot memory currSnapshot = IStorageHistory(currStorageHistory).deploymentSnapshot();
|
||||||
|
|
||||||
|
assertEq(prevSnapshot.amountIn, currSnapshot.amountIn);
|
||||||
|
assertEq(prevSnapshot.amountOut, currSnapshot.amountOut);
|
||||||
|
assertEq(prevSnapshot.deployedAt, currSnapshot.deployedAt);
|
||||||
|
|
||||||
|
assert(IStorageHistory(prevStorageHistory).isTransactionExecuted(exodusSession));
|
||||||
|
assert(IStorageHistory(currStorageHistory).isTransactionExecuted(exodusSession));
|
||||||
|
|
||||||
|
assertEq(gatekeeper.existentialDeposit(), EXISTENTIAL);
|
||||||
|
assertEq(staking.gatekeeper().existentialDeposit(), EXISTENTIAL + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user