implement linear dynamic gas pricing and update execution buffer

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-09-24 16:48:05 +03:00
parent de2e49c877
commit 5f01391cb7
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
2 changed files with 80 additions and 11 deletions

View File

@ -22,15 +22,17 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
using GovernancePacking for GovernancePacking.GovernancePayload;
uint256 public constant BOUNTY_DIVISOR = type(uint32).max;
uint256 public constant EXISTENTIAL_DEPOSIT = 500 * 1e12; // 0.005
uint256 public constant FULL_GAS_RESTORATION_TIME = 3600; // 1 hour
uint256 public constant MAX_ALLOWED_GAS_PRICE = 3e9; // 3 gwei
uint256 public constant EXISTENTIAL_DEPOSIT = 500 * 1e12;
uint256 public constant GAS_EXECUTION_BUFFER = 33805;
uint256 public constant GAS_EXECUTION_BUFFER = 21000 + 5969 + 50955;
uint256 public constant REGISTRY_INDEX = 0;
address public override staking;
address public override deployer;
address public override storageHistory;
uint256 private _lastVerificationTime;
address private _previousAddress;
bool private _initialized;
@ -109,6 +111,16 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
return (publicKey, state.parity, state.session);
}
function getCurrentGasPrice() public view returns (uint256) {
uint256 timePassed = block.timestamp - _lastVerificationTime;
if (timePassed >= FULL_GAS_RESTORATION_TIME) {
return MAX_ALLOWED_GAS_PRICE;
}
return FullMath.mulDiv(MAX_ALLOWED_GAS_PRICE, timePassed, FULL_GAS_RESTORATION_TIME);
}
function ghost(bytes32 receiver, uint256 amount) external override {
if (msg.sender != staking) revert NotStaking();
if (amount < EXISTENTIAL_DEPOSIT) revert NonExistentAmount();
@ -121,25 +133,24 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
bytes calldata call,
uint256 rx,
uint256 s
) external nonReentrant returns (bytes memory) {
) external nonReentrant {
uint256 gasStart = gasleft();
uint256 px = _extractPublicKey(call);
bool validSignature = Verifier.verifyGhost(call, px, rx, s);
if (!validSignature) revert BadSignature();
(bool success, bytes memory data) = address(this).call(call);
(bool success,) = address(this).call(call);
if (!success) revert ExecutionReverted();
uint256 gasPrice = MAX_ALLOWED_GAS_PRICE < tx.gasprice ? MAX_ALLOWED_GAS_PRICE : tx.gasprice;
uint256 gasSpent = (gasStart - gasleft() + GAS_EXECUTION_BUFFER) * gasPrice;
uint256 currentGasPrice = getCurrentGasPrice();
_lastVerificationTime = block.timestamp;
uint256 gasSpent = (gasStart - gasleft() + GAS_EXECUTION_BUFFER) * currentGasPrice;
try IStaking(staking).phantomRefund(msg.sender, gasSpent, REGISTRY_INDEX) {}
catch {
emit VoluntaryVerification(msg.sender, gasSpent);
}
return data;
}
function recall(
@ -192,7 +203,7 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
function govern(
uint256 exodusSession,
uint256 packed,
bytes calldata
bytes calldata call
) external {
if (msg.sender != address(this)) revert NotGatekeeper();
@ -201,7 +212,7 @@ contract Gatekeeper is IGatekeeper, Weaver, ReentrancyGuard {
StorageHistory(storageHistory).trySetTransactionExecuted(exodusSession);
(bool success,) = payload.target.call(msg.data[132:]);
(bool success,) = payload.target.call(call);
if (!success) revert ExecutionReverted();
}

View File

@ -92,6 +92,64 @@ contract GatekeeperRecallTest is Test {
vm.stopPrank();
}
function test_gasPriceCorrectDuringRecall() public {
vm.startPrank(INITIALIZER);
Gatekeeper gatekeeper = Gatekeeper(payable(staking.gatekeeper()));
gatekeeper.updatePublicKeyMetadata(0, 0xb5cd0d028a5e1b6a4eecb113b7e49c8176385eb77c8f134bc1db4bddd7654de6, 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();
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() * 69);
uint256 bobBalanceBeforeFirst = ghst.balanceOf(BOB);
uint256 priceBeforeFirst = gatekeeper.getCurrentGasPrice();
assertEq(priceBeforeFirst, gatekeeper.MAX_ALLOWED_GAS_PRICE());
assertEq(ghst.balanceOf(BOB), 0);
vm.prank(BOB, BOB);
gatekeeper.verify(
hex"bf06188a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000017508f1956a800000000000000000000000000000000000000000020000000000007a6980000000",
0x883302783b7f3d253d5bdeb17f39117641acdf061bf3fe457cb505df6b17dfc1,
0x8c3fc03b5cb738777ceec396ee8647f782d6670992f8f973de2dfc83379978d5
);
uint256 bobBalanceAfterFirst = ghst.balanceOf(BOB);
assertGt(bobBalanceAfterFirst, bobBalanceBeforeFirst);
assertEq(gatekeeper.getCurrentGasPrice(), 0);
vm.prank(BOB, BOB);
gatekeeper.verify(
hex"3137142600000000000000000000000000000000000000000000000000000000000000120000000000007a69010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000042b7ce50000000000000000000000000000000000000000000000000000000000",
0xf1f4d62d27c3d0388b2298b621b23cd5791e1b97d4423ffc16b14e81ff0df97c,
0xdbeed3eb94a829710147595c1b10f2ac6ec761c9721d8cc4711842c212ac517e
);
assertEq(ghst.balanceOf(BOB), bobBalanceAfterFirst);
assertEq(gatekeeper.getCurrentGasPrice(), 0);
vm.warp(block.timestamp + gatekeeper.FULL_GAS_RESTORATION_TIME() / 2);
uint256 gasPriceRestored = gatekeeper.getCurrentGasPrice();
assertEq(gasPriceRestored, gatekeeper.MAX_ALLOWED_GAS_PRICE() / 2);
vm.prank(BOB, BOB);
gatekeeper.verify(
hex"31371426000000000000000000000000000000000000000000000000000000000000000d0000000000007a6901010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064e4e33ef800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000",
0x0716f763060cfd52339544a203d0e156a42370b0e22d78ea9bf8766b0b66682b,
0xc2da93948f869c5102992bd1cbd70ef5f821ff522305c69d113faf2e89570ce7
);
assertGt(ghst.balanceOf(BOB), bobBalanceAfterFirst);
assertEq(gatekeeper.getCurrentGasPrice(), 0);
}
function test_recallChainWorks() public {
vm.startPrank(INITIALIZER);
Gatekeeper gatekeeper = Gatekeeper(payable(staking.gatekeeper()));