Skip to content

Conversation

@0xhaz
Copy link

@0xhaz 0xhaz commented Dec 22, 2025

Summary

Implement StakingFacet and StakingMod

Checklist

Before submitting this PR, please ensure:

  • Code follows the Solidity feature ban - No inheritance, constructors, modifiers, public/private variables, external library functions, using for directives, or selfdestruct

  • Code follows Design Principles - Readable, uses diamond storage, favors composition over inheritance

  • Code matches the codebase style - Consistent formatting, documentation, and patterns (e.g. ERC20Facet.sol)

  • Code is formatted with forge fmt

  • Existing tests pass - Run tests to be sure existing tests pass.

  • New tests are optional - If you don't provide tests for new functionality or changes then please create a new issue so this can be assigned to someone.

  • All tests pass - Run forge test and ensure everything works

  • Documentation updated - If applicable, update relevant documentation

Make sure to follow the contributing guidelines.

@netlify
Copy link

netlify bot commented Dec 22, 2025

👷 Deploy request for compose-diamonds pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 6dc6b60

@0xhaz
Copy link
Author

0xhaz commented Dec 22, 2025

Hi @maxnorm , kindly review this PR and let met know if there's any structure or style that needs to be amend. Thanks!

@github-actions
Copy link

github-actions bot commented Dec 22, 2025

Coverage Report

Coverage

Metric Coverage Details
Lines 85% 1676/1964 lines
Functions 86% 361/421 functions
Branches 67% 189/283 branches

Last updated: Tue, 23 Dec 2025 21:30:40 GMT for commit 6dc6b60

@github-actions
Copy link

Gas Report

No gas usage changes detected between main and feat/staking.

All functions maintain the same gas costs. ✅

Last updated: Tue, 23 Dec 2025 00:05:34 GMT for commit 439d8e9

Copy link
Contributor

@mudgen mudgen left a comment

Choose a reason for hiding this comment

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

Hi @0xhaz,

I appreciate your work on this. I looked at some of this implementation and left some comments. This staking functionality will/would require a lot of additional research and work.

I think we should probably put a pause on this functionality because I realize now that we may will not need it because some developers are currently working on an implementation of ERC4626 for Compose that might take care of most staking needs.

Comment on lines +46 to +47
uint256 stakedAt;
uint256 lastClaimedAt;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use uint64 for timestamps that are stored in contract storage. That will use less gas for writing and reading when they are packed together.

}
stakeERC20(_tokenAddress, _amount);
} else if (s.supportedTokens[_tokenAddress].isERC721) {
if (IERC721(_tokenAddress).ownerOf(_tokenId) != msg.sender) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see a need here to check the owner of a token here because that will be done in by the transferFrom function.

if (IERC721(_tokenAddress).ownerOf(_tokenId) != msg.sender) {
revert StakingNotTokenOwner(msg.sender, _tokenAddress, _tokenId);
}
IERC721(_tokenAddress).safeTransferFrom(msg.sender, address(this), _tokenId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why use safeTransferFrom here instead of transferFrom? transferFrom would be better in this case because it would avoid an unnecessary call that safeTransferFrom makes.

IERC721(_tokenAddress).safeTransferFrom(msg.sender, address(this), _tokenId);
stakeERC721(_tokenAddress, _tokenId);
} else if (s.supportedTokens[_tokenAddress].isERC1155) {
if (IERC1155(_tokenAddress).balanceOf(msg.sender, _tokenId) < _amount) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see why we need to check the balance here because this would be done by the safeTransferFrom function.

revert StakingUnsupportedToken(_tokenAddress);
}

if (s.minStakeAmount > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see why we are checking s.minStakeAmount here when setStakingParameters reverts if the value is 0.

}

if (s.supportedTokens[_tokenAddress].isERC20) {
bool success = IERC20(_tokenAddress).transferFrom(msg.sender, address(this), _amount);
Copy link
Contributor

Choose a reason for hiding this comment

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

ERC20 transfer edge cases are not mentioned or handled here.

Comment on lines +280 to +281
uint256 maxStakeAmount;
uint256 minStakeAmount;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are max and min stake amount requirements needed?

@mudgen mudgen closed this Dec 23, 2025
@mudgen mudgen mentioned this pull request Dec 23, 2025
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