Skip to content

Implement native coin fee mechanism#52

Open
andreygLime wants to merge 2 commits into
v2from
handle-flat-fee
Open

Implement native coin fee mechanism#52
andreygLime wants to merge 2 commits into
v2from
handle-flat-fee

Conversation

@andreygLime
Copy link
Copy Markdown
Collaborator

Replaced the per-token percentage-based fee system with a native gas coin fee collected via msg.value on lock and burn operations.

New contracts

  • LibFeeDistributor / FeeDistributorFacet — accumulates and distributes native coin fees to validators
  • GovernanceFacetV3 — upgrades updateMember to handle both ERC-20 (legacy) and native coin fee claims on member removal
  • RouterFacetV2lock, burn, lockWithPermit, burnWithPermit are now payable; updateNativeToken simplified to (address, bool) (fee percentage removed)
  • IRouterV2 / IFeeDistributor / IGovernanceV2 — corresponding interfaces

Upgrade path (backward-compatible with mainnet)

  • upgrade-governance-v2.js — V1 → V2 (replaces updateMember with LibPayment support)
  • upgrade-governance-v3.js — V2 → V3 + adds FeeDistributorFacet + replaces router functions with RouterFacetV2
  • deploy-router.js — fresh deployments now chain V1 → V2 → V3

Updated scripts

  • lock-erc-20, burn-erc-20 — accept serviceFee param, send as msg.value
  • update-native-token — removed feePercentage param
  • erc-20-unlock — uses IRouterV2 ABI
  • Hardhat tasks updated accordingly

Tests

  • Full test suite updated for FeeDistributorFacet, RouterFacetV2, and native coin fee flow

@andreygLime andreygLime requested a review from vlady-kotsev March 5, 2026 09:04
mapping(address => uint256) claimedRewardsPerAccount;
}

struct Storage {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for two structs for FeeDistributor

bytes32 constant STORAGE_POSITION = keccak256("fee.distributor.storage");

/// @notice Accumulates fees distributed among validators
struct FeeCalculator {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to Storage

view
override
returns (
uint256 feesAccrued,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for named returns, we don't use them

Comment thread contracts/facets/GovernanceFacetV3.sol Outdated
LibDiamond.enforceIsContractOwner();

if (_status) {
for (uint256 i = 0; i < LibRouter.nativeTokensCount(); i++) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move LibRouter.nativeTokensCount() outside of for loop
move i++ inside unchecked block

@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets add IGovernanceV3.sol. With a spec doc explaining why it exists, I think for clarity is better to not have GovernanceFacetV3 implement IGovernanceV2.

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use current convention for facet versioning: GovernanceV3Facet

return claimableAmount;
}

/// @notice Records an incoming fees into the accumulator
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not recording into the accumulator. Also I think distributeFee is a little misleading name. Let's stick with accrueFee

Comment thread contracts/interfaces/IRouterV2.sol Outdated
event Lock(
uint256 targetChain,
address token,
uint256 amount,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check params order compared to IRouteV1

uint256 claimableFees = LibFeeCalculator.claimReward(
_account,
token
);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add zero check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants