{"id":18299981,"url":"https://github.com/chorusone/fee-manager-contract","last_synced_at":"2026-01-20T09:33:44.664Z","repository":{"id":220354204,"uuid":"679946709","full_name":"ChorusOne/fee-manager-contract","owner":"ChorusOne","description":"Contracts for managing validator's rewards fees","archived":false,"fork":false,"pushed_at":"2024-08-14T17:34:45.000Z","size":79,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-19T16:49:20.490Z","etag":null,"topics":["opus-team"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChorusOne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-18T01:47:31.000Z","updated_at":"2024-04-30T06:49:33.000Z","dependencies_parsed_at":"2024-08-14T18:30:02.635Z","dependency_job_id":"61048384-d3cf-4fa0-b7b0-cacc8aeedd64","html_url":"https://github.com/ChorusOne/fee-manager-contract","commit_stats":null,"previous_names":["chorusone/fee-manager-contract"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ChorusOne/fee-manager-contract","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Ffee-manager-contract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Ffee-manager-contract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Ffee-manager-contract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Ffee-manager-contract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChorusOne","download_url":"https://codeload.github.com/ChorusOne/fee-manager-contract/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Ffee-manager-contract/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28600628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T08:51:33.170Z","status":"ssl_error","status_checked_at":"2026-01-20T08:51:10.855Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["opus-team"],"created_at":"2024-11-05T15:11:01.732Z","updated_at":"2026-01-20T09:33:44.650Z","avatar_url":"https://github.com/ChorusOne.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fee-manager-contract\n\nContracts for managing validator's rewards fees\n\n## Overview\n\n- The repo contains 2 contracts: `FeeRewardsManager` and `RewardsCollector` and a library `CalculateAndSendRewards`\n- Fee manager contract `FeeRewardsManager` will be deployed once per environment.\n- `FeeRewardsManager` creates one `RewardsCollector` contract per withdrawal credentials (some users may have more than 1)\n- On creation `FeeRewardsManager` sets a default commission fee and has permission to change that fee.\n- `RewardsCollector` address will be derived from `withdrawal credentials`.\n- `RewardsCollector` address will be set as `fee_recipient` for customers validators and earn execution rewards.\n- `collectRewards` function in `RewardsCollector` contract can be triggered to send rewards minus commission fee to withdrawal .address.\n\n### `RewardsCollector` Contract\n\n- **Ownership**: This contract does not explicitly use an ownership model. Instead, it references a `parentContract`, the contract that deployed it, the `FeeRewardsManager` contract.\n- **withdrawalCredential**: A crucial address that is set upon contract deployment, determining where a portion of the fees are sent.\n- **feeNumerator**: A value determining the fee percentage, modifiable only by the `parentContract`.\n\n### `FeeRewardsManager` Contract\n\n- **Ownership**: Inherits from `Ownable2Step`, a variant of the OpenZeppelin `Ownable` contract, which provides a secure ownership model with a two-step transfer process to prevent accidental loss of ownership. The part that is receiving\nthe ownership on the transfer must confirm it with a transaction.\n- **defaultFeeNumerator**: Set upon deployment and modifiable by the contract owner.\n- **Eth Withdrawal**: Only the owner can withdraw Eth from the contract.\n\n## Deploying\n\nCopy and populate `.env.dist` to `.env` in the root directory\nTo deploy to Goerli, run:\n\n```\nforge script ./script/FeeRewardsManager.s.sol --verify --broadcast --rpc-url goerli --private-key ${PRIVATE_KEY}\n```\n\nSwitch to `--rpc-url mainnet` making sure the `mainnet` RPC endpoint exists in the `foundry.toml` file.\nIf deploying with a ledger, instead of `--private-key ${PRIVATE_KEY}`, use `--ledger`.\n\n## Deployments\n\nThis contract is currently deployed on:\n\n| Network      | FeeRewardsManager     | CalculateAndSendRewards |\n|--------------|-----------------------|-------------------------|\n| Mainnet | [0x5Bab02440602302Fb20906B04051e5D6c074D57f](https://etherscan.io/address/0x5Bab02440602302Fb20906B04051e5D6c074D57f) | [0x8D03884EF3F39ec263F3D7c3954A868468ff8497](https://etherscan.io/address/0x8D03884EF3F39ec263F3D7c3954A868468ff8497)|\n| Goerli | [0x3ca56c8ba036adb672215dc5ed4577a3f1a239d3](https://goerli.etherscan.io/address/0x3ca56c8ba036adb672215dc5ed4577a3f1a239d3) | [0x7f18c4901b68d6aebac40b2e2f5ec3516d95ee2a](https://goerli.etherscan.io/address/0x7f18c4901b68d6aebac40b2e2f5ec3516d95ee2a) |\n| Holesky | [0x8Ef21C0E9d86230cdD73C816cb48987Da3CDaF22](https://holesky.etherscan.io/address/0x8Ef21C0E9d86230cdD73C816cb48987Da3CDaF22) | [0x096874A27f6f9838dCB1422098D389852007244b](https://holesky.etherscan.io/address/0x096874A27f6f9838dCB1422098D389852007244b) |\n\n## Walkthrough a normal execution\n\nDeploy `FeeRewardsManager` as `manager`, then we call\n`predictFeeContractAddress(_withdrawalCredential)` passing the validator's\nwithdrawal credentials, the function can be called offline and produces a\ndeterministic `collector` address for the withdrawal credential.\nWe set the `collector` address as the `fee recipient` for the validator. Observe\nthat the `collector` address can start receiving Ether even if the contract is not deployed,\nwe can delay the execution of `manager` that creates the `collector` contract to a convenient time.\nLet's say the validator accumulated 10 Ether in rewards in the `collector` address.\n\nAnyone can decide to call `createFeeContract` in the `manager` contract, passing the\nwithdrawal credentials, this will create the `collector` contract where the `collector` address was in place,\nnote that the contract state will already have 10 Ether.\nBy default, the `manager` contract gets `collector.balance * x` and the\n`withdrawal_credential` contract gets the rest of the Ether (`collector.balance - collector.balance * x`).\nthe `manager` contract has a default tax, it gets *copied* to the `collector` contract during contract creation,\nthese tax can be modified by the owner of the `manager` contract.\n\nLet's assume the tax `x` is 28% and\nan someone decides to call `collectRewards` in\nthe `collector` contract, this contract splits the 10 Ether\nrewards in 2:\n    `10*28%` = 2.8 Ether goes to the `manager` contract.\n    `10 - 2.8` = 7.2 Ether goes to the `withdrawal credential` associated with the contract.\n\nFinally, the owner of `manager` can call `getEth` specifying an address to\nreceive the Ether accumulated in the contract.\n\n## Trust Model\n\nChorus One operates the Ethereum validators with this smart contract. They provide a\nsmart contract that should be used as the validator's fee recipient.\nUsers are required to place a significant amount of trust in Chorus One. This\ntrust encompasses:\n\n1. **Validator Operation**: Users trust that Chorus One will operate its\nvalidators effectively and in compliance with the network's protocols.\nSlashing penalties are imposed on validators for actions deemed harmful to the\nnetwork, like double signing or downtime. Users trust that Chorus One\nwill avoid behaviors that could trigger these penalties, as slashing can lead to\na partial loss of the staked assets.\n\n2. **Management of Validator Fees**: Validator fees are a portion of the rewards\nearned by validators for their service to the network. Users trust that\nChorus One will maintain transparency and fairness in setting and distributing\nthese fees and not alter the recipient of these fees without clear communication\nand rationale.\n\n3. **Exit Validators on User's behalf**: Users might request to exit their validators,\nin this case, they trust that Chorus One will exit the validators according to user requests.\n\nUsers should perform due diligence and continually monitor the validator's\nperformance and reputation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchorusone%2Ffee-manager-contract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchorusone%2Ffee-manager-contract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchorusone%2Ffee-manager-contract/lists"}