Skip to content

Commit

Permalink
undo tokenomics
Browse files Browse the repository at this point in the history
  • Loading branch information
dantaik committed Dec 2, 2022
1 parent 89e9d78 commit d51fe1f
Show file tree
Hide file tree
Showing 8 changed files with 9 additions and 264 deletions.
3 changes: 0 additions & 3 deletions packages/protocol/contracts/L1/LibData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ library LibData {
// 3 slots
struct ProposedBlock {
bytes32 metaHash;
uint256 deposit;
address proposer;
uint64 proposedAt;
}
Expand All @@ -56,8 +55,6 @@ library LibData {
uint64 genesisTimestamp;
uint64 __reservedA1;
uint64 statusBits; // rarely change
// Changed when a block is proposed or proven/finalized
uint256 feeBase;
// Changed when a block is proposed
uint64 nextBlockId;
uint64 lastProposedAt; // Timestamp when the last block is proposed.
Expand Down
25 changes: 2 additions & 23 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,10 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events {

function init(
address _addressManager,
bytes32 _genesisBlockHash,
uint256 _feeBase
bytes32 _genesisBlockHash
) external initializer {
EssentialContract._init(_addressManager);
V1Verifying.init({
state: state,
genesisBlockHash: _genesisBlockHash,
feeBase: _feeBase
});
V1Verifying.init({state: state, genesisBlockHash: _genesisBlockHash});

tentative.whitelistProposers = false;
tentative.whitelistProvers = true;
Expand Down Expand Up @@ -253,22 +248,6 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events {
return V1Utils.isProverWhitelisted(tentative, prover);
}

function getBlockFee() public view returns (uint256) {
(, uint fee, uint deposit) = V1Proposing.getBlockFee(state);
return fee + deposit;
}

function getProofReward(
uint64 provenAt,
uint64 proposedAt
) public view returns (uint256 reward) {
(, reward, ) = V1Verifying.getProofReward({
state: state,
provenAt: provenAt,
proposedAt: proposedAt
});
}

/**
* Check if the L1 is halted.
* @return True if halted, false otherwise.
Expand Down
48 changes: 0 additions & 48 deletions packages/protocol/contracts/L1/v1/V1Proposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,38 +98,10 @@ library V1Proposing {
meta.mixHash = bytes32(block.difficulty);
}

uint256 deposit;
if (LibConstants.K_TOKENOMICS_ENABLED) {
uint256 newFeeBase;
{
uint256 fee;
(newFeeBase, fee, deposit) = getBlockFee(state);
TkoToken(resolver.resolve("tko_token")).burn(
msg.sender,
fee + deposit
);
}
// Update feeBase and avgBlockTime
state.feeBase = V1Utils.movingAverage({
maValue: state.feeBase,
newValue: newFeeBase,
maf: LibConstants.K_FEE_BASE_MAF
});

state.avgBlockTime = V1Utils
.movingAverage({
maValue: state.avgBlockTime,
newValue: meta.timestamp - state.lastProposedAt,
maf: LibConstants.K_BLOCK_TIME_MAF
})
.toUint64();
}

state.saveProposedBlock(
state.nextBlockId,
LibData.ProposedBlock({
metaHash: LibData.hashMetadata(meta),
deposit: deposit,
proposer: msg.sender,
proposedAt: meta.timestamp
})
Expand All @@ -139,26 +111,6 @@ library V1Proposing {
emit BlockProposed(state.nextBlockId++, meta);
}

function getBlockFee(
LibData.State storage state
) public view returns (uint256 newFeeBase, uint256 fee, uint256 deposit) {
(newFeeBase, ) = V1Utils.getTimeAdjustedFee({
state: state,
isProposal: true,
tNow: uint64(block.timestamp),
tLast: state.lastProposedAt,
tAvg: state.avgBlockTime,
tCap: LibConstants.K_BLOCK_TIME_CAP
});
fee = V1Utils.getSlotsAdjustedFee({
state: state,
isProposal: true,
feeBase: newFeeBase
});
fee = V1Utils.getBootstrapDiscountedFee(state, fee);
deposit = (fee * LibConstants.K_PROPOSER_DEPOSIT_PCTG) / 100;
}

function isCommitValid(
LibData.State storage state,
uint256 commitSlot,
Expand Down
71 changes: 0 additions & 71 deletions packages/protocol/contracts/L1/v1/V1Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,65 +93,6 @@ library V1Utils {
return tentative.provers[prover];
}

// Implement "Incentive Multipliers", see the whitepaper.
function getTimeAdjustedFee(
LibData.State storage state,
bool isProposal,
uint64 tNow,
uint64 tLast,
uint64 tAvg,
uint64 tCap
) internal view returns (uint256 newFeeBase, uint256 tRelBp) {
if (tAvg == 0) {
newFeeBase = state.feeBase;
tRelBp = 0;
} else {
uint256 _tAvg = tAvg > tCap ? tCap : tAvg;
uint256 tGrace = (LibConstants.K_FEE_GRACE_PERIOD_PCTG * _tAvg) /
100;
uint256 tMax = (LibConstants.K_FEE_MAX_PERIOD_PCTG * _tAvg) / 100;
uint256 a = tLast + tGrace;
uint256 b = tNow > a ? tNow - a : 0;
tRelBp = (b.min(tMax) * 10000) / tMax; // [0 - 10000]
uint256 alpha = 10000 +
((LibConstants.K_REWARD_MULTIPLIER_PCTG - 100) * tRelBp) /
100;
if (isProposal) {
newFeeBase = (state.feeBase * 10000) / alpha; // fee
} else {
newFeeBase = (state.feeBase * alpha) / 10000; // reward
}
}
}

// Implement "Slot-availability Multipliers", see the whitepaper.
function getSlotsAdjustedFee(
LibData.State storage state,
bool isProposal,
uint256 feeBase
) internal view returns (uint256) {
// m is the `n'` in the whitepaper
uint256 m = LibConstants.K_MAX_NUM_BLOCKS -
1 +
LibConstants.K_FEE_PREMIUM_LAMDA;
// n is the number of unverified blocks
uint256 n = state.nextBlockId - state.latestVerifiedId - 1;
// k is `m − n + 1` or `m − n - 1`in the whitepaper
uint256 k = isProposal ? m - n - 1 : m - n + 1;
return (feeBase * (m - 1) * m) / (m - n) / k;
}

// Implement "Bootstrap Discount Multipliers", see the whitepaper.
function getBootstrapDiscountedFee(
LibData.State storage state,
uint256 feeBase
) internal view returns (uint256) {
uint256 halves = uint256(block.timestamp - state.genesisTimestamp) /
LibConstants.K_HALVING;
uint256 gamma = 1024 - (1024 >> halves);
return (feeBase * gamma) / 1024;
}

// Returns a deterministic deadline for uncle proof submission.
function uncleProofDeadline(
LibData.State storage state,
Expand All @@ -160,18 +101,6 @@ library V1Utils {
return fc.provenAt + state.avgProofTime;
}

function movingAverage(
uint256 maValue,
uint256 newValue,
uint256 maf
) internal pure returns (uint256) {
if (maValue == 0) {
return newValue;
}
uint256 _ma = (maValue * (maf - 1) + newValue) / maf;
return _ma > 0 ? _ma : maValue;
}

function setBit(
LibData.State storage state,
uint64 mask,
Expand Down
95 changes: 1 addition & 94 deletions packages/protocol/contracts/L1/v1/V1Verifying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,10 @@ library V1Verifying {

function init(
LibData.State storage state,
bytes32 genesisBlockHash,
uint256 feeBase
bytes32 genesisBlockHash
) public {
require(feeBase > 0, "L1:feeBase");

state.genesisHeight = uint64(block.number);
state.genesisTimestamp = uint64(block.timestamp);
state.feeBase = feeBase;
state.nextBlockId = 1;
state.lastProposedAt = uint64(block.timestamp);
state.l2Hashes[0] = genesisBlockHash;
Expand All @@ -58,57 +54,18 @@ library V1Verifying {
uint64 latestL2Height = state.latestVerifiedHeight;
bytes32 latestL2Hash = state.l2Hashes[latestL2Height];
uint64 processed = 0;
TkoToken tkoToken;

for (
uint256 i = state.latestVerifiedId + 1;
i < state.nextBlockId && processed <= maxBlocks;
i++
) {
LibData.ForkChoice storage fc = state.forkChoices[i][latestL2Hash];
LibData.ProposedBlock storage target = LibData.getProposedBlock(
state,
i
);

// Uncle proof can not take more than 2x time the first proof did.
if (!_isVerifiable(state, fc)) {
break;
} else {
if (LibConstants.K_TOKENOMICS_ENABLED) {
uint256 newFeeBase;
{
uint256 reward;
uint256 tRelBp; // [0-10000], see the whitepaper
(newFeeBase, reward, tRelBp) = getProofReward({
state: state,
provenAt: fc.provenAt,
proposedAt: target.proposedAt
});

if (address(tkoToken) == address(0)) {
tkoToken = TkoToken(resolver.resolve("tko_token"));
}

_rewardProvers(fc, reward, tkoToken);
_refundProposerDeposit(target, tRelBp, tkoToken);
}
// Update feeBase and avgProofTime
state.feeBase = V1Utils.movingAverage({
maValue: state.feeBase,
newValue: newFeeBase,
maf: LibConstants.K_FEE_BASE_MAF
});

state.avgProofTime = V1Utils
.movingAverage({
maValue: state.avgProofTime,
newValue: fc.provenAt - target.proposedAt,
maf: LibConstants.K_PROOF_TIME_MAF
})
.toUint64();
}

if (fc.blockHash != LibConstants.K_BLOCK_DEADEND_HASH) {
latestL2Height += 1;
latestL2Hash = fc.blockHash;
Expand All @@ -130,56 +87,6 @@ library V1Verifying {
}
}

function getProofReward(
LibData.State storage state,
uint64 provenAt,
uint64 proposedAt
) public view returns (uint256 newFeeBase, uint256 reward, uint256 tRelBp) {
(newFeeBase, tRelBp) = V1Utils.getTimeAdjustedFee({
state: state,
isProposal: false,
tNow: provenAt,
tLast: proposedAt,
tAvg: state.avgProofTime,
tCap: LibConstants.K_PROOF_TIME_CAP
});
reward = V1Utils.getSlotsAdjustedFee({
state: state,
isProposal: false,
feeBase: newFeeBase
});
reward = (reward * (10000 - LibConstants.K_REWARD_BURN_BP)) / 10000;
}

function _refundProposerDeposit(
LibData.ProposedBlock storage target,
uint256 tRelBp,
TkoToken tkoToken
) private {
uint refund = (target.deposit * (10000 - tRelBp)) / 10000;
if (refund > 0) {
tkoToken.mint(target.proposer, refund);
}
}

function _rewardProvers(
LibData.ForkChoice storage fc,
uint256 reward,
TkoToken tkoToken
) private {
uint sum = 2 ** fc.provers.length - 1;
for (uint i = 0; i < fc.provers.length; i++) {
uint weight = (1 << (fc.provers.length - i - 1));
uint proverReward = (reward * weight) / sum;

if (tkoToken.balanceOf(fc.provers[i]) == 0) {
// reduce reward if the prover has 0 TKO balance.
proverReward /= 2;
}
tkoToken.mint(fc.provers[i], proverReward);
}
}

function _cleanUp(LibData.ForkChoice storage fc) private {
fc.blockHash = 0;
fc.provenAt = 0;
Expand Down
10 changes: 5 additions & 5 deletions packages/protocol/contracts/L2/V1TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync {
publicInputHash = _hashPublicInputs({
chainId: block.chainid,
number: number,
feeBase: 0,
baseFee: 0,
ancestors: ancestors
});
}
Expand Down Expand Up @@ -189,7 +189,7 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync {
_hashPublicInputs({
chainId: chainId,
number: parentHeight,
feeBase: 0,
baseFee: 0,
ancestors: ancestors
}),
"L2:publicInputHash"
Expand All @@ -199,7 +199,7 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync {
publicInputHash = _hashPublicInputs({
chainId: chainId,
number: number,
feeBase: 0,
baseFee: 0,
ancestors: ancestors
});

Expand All @@ -209,9 +209,9 @@ contract V1TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync {
function _hashPublicInputs(
uint256 chainId,
uint256 number,
uint256 feeBase,
uint256 baseFee,
bytes32[255] memory ancestors
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(chainId, number, feeBase, ancestors));
return keccak256(abi.encodePacked(chainId, number, baseFee, ancestors));
}
}
Loading

0 comments on commit d51fe1f

Please sign in to comment.