diff --git a/spec/gar_spec.lua b/spec/gar_spec.lua index c740ec7a..da018512 100644 --- a/spec/gar_spec.lua +++ b/spec/gar_spec.lua @@ -1,3 +1,4 @@ +local constants = require("constants") local gar = require("gar") local utils = require("utils") @@ -836,8 +837,8 @@ describe("gar", function() it("should decrease delegated stake with instant withdrawal and apply penalty and remove delegate", function() Balances[ao.id] = 0 - local penaltyAmount = 1000 * 0.80 - local withdrawalAmount = 1000 - penaltyAmount + local expenditedWithdrawalFee = 1000 * 0.80 + local withdrawalAmount = 1000 - expenditedWithdrawalFee GatewayRegistry[stubGatewayAddress] = { operatorStake = gar.getSettings().operators.minStake, totalDelegatedStake = gar.getSettings().delegates.minStake + 1000, @@ -878,7 +879,7 @@ describe("gar", function() assert.are.same(result.delegates[stubRandomAddress].delegatedStake, gar.getSettings().delegates.minStake) assert.are.equal(result.totalDelegatedStake, gar.getSettings().delegates.minStake) assert.are.equal(withdrawalAmount, Balances[stubRandomAddress]) - assert.are.equal(penaltyAmount, Balances[ao.id]) + assert.are.equal(expenditedWithdrawalFee, Balances[ao.id]) assert.are.equal( gar.getSettings().delegates.minStake, _G.GatewayRegistry[stubGatewayAddress].totalDelegatedStake @@ -893,9 +894,9 @@ describe("gar", function() local currentTimestamp = 1000000 local startTimestamp = 1000000 local vaultBalance = 1000 - local expectedPenaltyRate = 0.80 - local expectedPenaltyAmount = vaultBalance * expectedPenaltyRate - local expectedWithdrawalAmount = vaultBalance - expectedPenaltyAmount + local expectedPenaltyRate = constants.MAX_EXPEDITED_WITHDRAWAL_FEE + local expectedexpenditedWithdrawalFee = vaultBalance * expectedPenaltyRate + local expectedWithdrawalAmount = vaultBalance - expectedexpenditedWithdrawalFee Balances[ao.id] = 0 @@ -942,7 +943,7 @@ describe("gar", function() assert.are.equal(nil, result.delegate) -- Delegate should be removed after full withdrawal assert.are.equal(0, result.totalDelegatedStake) assert.are.equal(expectedWithdrawalAmount, Balances[stubRandomAddress]) - assert.are.equal(expectedPenaltyAmount, Balances[ao.id]) + assert.are.equal(expectedexpenditedWithdrawalFee, Balances[ao.id]) assert.are.equal(0, _G.GatewayRegistry[stubGatewayAddress].totalDelegatedStake) end ) @@ -957,12 +958,13 @@ describe("gar", function() local elapsedTime = 15 * 24 * 60 * 60 * 1000 -- Half of 30 days in milliseconds local currentTimestamp = startTimestamp + elapsedTime local vaultBalance = 1000 - local maxPenalty = 0.80 - local minPenalty = 0.05 - local penaltyRate = maxPenalty - - ((maxPenalty - minPenalty) * (elapsedTime / gar.getSettings().delegates.withdrawLengthMs)) - local expectedPenaltyAmount = math.floor(vaultBalance * penaltyRate) - local expectedWithdrawalAmount = vaultBalance - expectedPenaltyAmount + local penaltyRate = constants.MAX_EXPEDITED_WITHDRAWAL_FEE + - ( + (constants.MAX_EXPEDITED_WITHDRAWAL_FEE - constants.MIN_EXPEDITED_WITHDRAWAL_FEE) + * (elapsedTime / gar.getSettings().delegates.withdrawLengthMs) + ) + local expectedexpenditedWithdrawalFee = math.floor(vaultBalance * penaltyRate) + local expectedWithdrawalAmount = vaultBalance - expectedexpenditedWithdrawalFee Balances[ao.id] = 0 _G.GatewayRegistry[stubGatewayAddress] = { @@ -1008,7 +1010,7 @@ describe("gar", function() assert.are.equal(nil, next(result.delegate.vaults)) -- Delegate should have no vaults remaining assert.are.equal(remainingDelegateStakeBalance, result.totalDelegatedStake) assert.are.equal(expectedWithdrawalAmount, Balances[stubRandomAddress]) - assert.are.equal(expectedPenaltyAmount, Balances[ao.id]) + assert.are.equal(expectedexpenditedWithdrawalFee, Balances[ao.id]) assert.are.equal( remainingDelegateStakeBalance, _G.GatewayRegistry[stubGatewayAddress].totalDelegatedStake @@ -1025,12 +1027,13 @@ describe("gar", function() local startTimestamp = 500000 local elapsedTime = 29 * 24 * 60 * 60 * 1000 -- Half of 30 days in milliseconds local currentTimestamp = startTimestamp + elapsedTime - local maxPenalty = 0.80 - local minPenalty = 0.05 - local penaltyRate = maxPenalty - - ((maxPenalty - minPenalty) * (elapsedTime / gar.getSettings().delegates.withdrawLengthMs)) - local expectedPenaltyAmount = math.floor(vaultBalance * penaltyRate) - local expectedWithdrawalAmount = vaultBalance - expectedPenaltyAmount + local penaltyRate = constants.MAX_EXPEDITED_WITHDRAWAL_FEE + - ( + (constants.MAX_EXPEDITED_WITHDRAWAL_FEE - constants.MIN_EXPEDITED_WITHDRAWAL_FEE) + * (elapsedTime / gar.getSettings().delegates.withdrawLengthMs) + ) + local expectedexpenditedWithdrawalFee = math.floor(vaultBalance * penaltyRate) + local expectedWithdrawalAmount = vaultBalance - expectedexpenditedWithdrawalFee Balances[ao.id] = 0 _G.GatewayRegistry[stubGatewayAddress] = { @@ -1076,7 +1079,7 @@ describe("gar", function() assert.are.equal(nil, result.delegate) -- Delegate should be removed after full withdrawal assert.are.equal(0, result.totalDelegatedStake) assert.are.equal(expectedWithdrawalAmount, Balances[stubRandomAddress]) - assert.are.equal(expectedPenaltyAmount, Balances[ao.id]) + assert.are.equal(expectedexpenditedWithdrawalFee, Balances[ao.id]) assert.are.equal(0, _G.GatewayRegistry[stubGatewayAddress].totalDelegatedStake) end ) diff --git a/src/constants.lua b/src/constants.lua index 5eee3c25..b70722a7 100644 --- a/src/constants.lua +++ b/src/constants.lua @@ -7,8 +7,8 @@ constants.oneYearSeconds = 60 * 60 * 24 * 365 constants.thirtyDaysSeconds = 60 * 60 * 24 * 30 constants.defaultundernameLimit = 10 constants.totalTokenSupply = 1000000000 * 1000000 -- 1 billion tokens -constants.MIN_WITHDRAW_PENALTY = 0.20 -constants.MAX_WITHDRAW_PENALTY = 0.80 +constants.MIN_EXPEDITED_WITHDRAWAL_FEE = 0.05 +constants.MAX_EXPEDITED_WITHDRAWAL_FEE = 0.80 -- ARNS constants.DEFAULT_UNDERNAME_COUNT = 10 diff --git a/src/gar.lua b/src/gar.lua index 220507db..ef0c273f 100644 --- a/src/gar.lua +++ b/src/gar.lua @@ -1,5 +1,6 @@ -- gar.lua local balances = require("balances") +local constants = require("constants") local utils = require("utils") local gar = {} @@ -376,12 +377,11 @@ function gar.decreaseDelegateStake(gatewayAddress, delegator, qty, currentTimest gateway.totalDelegatedStake = gateway.totalDelegatedStake - qty -- Calculate the penalty amount - local maxPenalty = 0.80 - local penaltyAmount = qty * maxPenalty - local amountToWithdraw = qty - penaltyAmount + local expenditedWithdrawalFee = qty * constants.MAX_EXPEDITED_WITHDRAWAL_FEE + local amountToWithdraw = qty - expenditedWithdrawalFee -- Add penalty to AR.IO protocol balance - balances.increaseBalance(ao.id, penaltyAmount) + balances.increaseBalance(ao.id, expenditedWithdrawalFee) -- Withdraw the remaining tokens to the delegate balances.increaseBalance(delegator, amountToWithdraw) @@ -804,19 +804,22 @@ function gar.instantDelegateWithdrawal(from, gatewayAddress, vaultId, currentTim end -- Calculate the penalty rate based on elapsed time - local maxPenalty = 0.80 - local minPenalty = 0.05 - local penaltyRate = maxPenalty - ((maxPenalty - minPenalty) * (elapsedTime / totalWithdrawalTime)) - penaltyRate = math.max(minPenalty, math.min(maxPenalty, penaltyRate)) -- Ensure penalty is within bounds + local penaltyRate = constants.MAX_EXPEDITED_WITHDRAWAL_FEE + - ( + (constants.MAX_EXPEDITED_WITHDRAWAL_FEE - constants.MIN_EXPEDITED_WITHDRAWAL_FEE) + * (elapsedTime / totalWithdrawalTime) + ) + penaltyRate = + math.max(constants.MIN_EXPEDITED_WITHDRAWAL_FEE, math.min(constants.MAX_EXPEDITED_WITHDRAWAL_FEE, penaltyRate)) -- Ensure penalty is within bounds -- Calculate the penalty amount and the amount to withdraw local vaultBalance = vault.balance - local penaltyAmount = math.floor(vaultBalance * penaltyRate) - local amountToWithdraw = vaultBalance - penaltyAmount + local expenditedWithdrawalFee = math.floor(vaultBalance * penaltyRate) + local amountToWithdraw = vaultBalance - expenditedWithdrawalFee -- Add penalty to AR.IO protocol balance - balances.increaseBalance(ao.id, penaltyAmount) + balances.increaseBalance(ao.id, expenditedWithdrawalFee) balances.increaseBalance(from, amountToWithdraw) -- Remove the vault after withdrawal