Skip to content

Commit

Permalink
Remove HAT bounty and use vault token for fee
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-kaufman committed Dec 22, 2023
1 parent 1deb982 commit e923bcc
Show file tree
Hide file tree
Showing 27 changed files with 744 additions and 3,336 deletions.
50 changes: 13 additions & 37 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -39,9 +37,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand Down Expand Up @@ -86,8 +82,7 @@ module.exports = {
]
}],
"hatVaultsRegistryConf": {
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "500"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand Down Expand Up @@ -129,9 +124,7 @@ module.exports = {
"rewardToken": "HATToken"
}],
"hatVaultsRegistryConf": {
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "500",
"swapToken": "HATToken"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -146,8 +139,7 @@ module.exports = {
"rewardControllersConf": [], // no reward controllers
"hatToken": "", // deploy a fresh HATToken contract
"hatVaultsRegistryConf": {
"bountyGovernanceHAT": "0",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
}
},
"polygon": {
Expand All @@ -165,9 +157,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -190,9 +180,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -215,9 +203,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -240,9 +226,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -265,9 +249,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -290,9 +272,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0x4200000000000000000000000000000000000006", // WETH
"hatVaultsRegistryConf": {
"swapToken": "0x4200000000000000000000000000000000000006", // WETH
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -315,9 +295,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "NEED ADDRESS", // USDC
"hatVaultsRegistryConf": {
"swapToken": "NEED ADDRESS", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand All @@ -340,9 +318,7 @@ module.exports = {
"rewardControllersConf": [],
"hatToken": "0xd86e243fc0007e6226b07c9a50c9d70d78299eb5", // USDC
"hatVaultsRegistryConf": {
"swapToken": "0xd86e243fc0007e6226b07c9a50c9d70d78299eb5", // USDC
"bountyGovernanceHAT": "1000",
"bountyHackerHATVested": "0"
"governanceFee": "1000"
},
"hatVaultsNFTConf": {
"merkleTreeIPFSRef": "",
Expand Down
90 changes: 29 additions & 61 deletions contracts/HATClaimsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,8 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu

PendingMaxBounty public pendingMaxBounty;

// the percentage of the total bounty to be swapped to HATs and sent to governance (out of {HUNDRED_PERCENT})
uint16 internal bountyGovernanceHAT;
// the percentage of the total bounty to be swapped to HATs and sent to the hacker via vesting contract (out of {HUNDRED_PERCENT})
uint16 internal bountyHackerHATVested;
// the fee percentage of the total bounty to be paid to the governance
uint16 internal governanceFee;

// address of the arbitrator - which can dispute claims and override the committee's decisions
address internal arbitrator;
Expand Down Expand Up @@ -122,11 +120,14 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
function initialize(IHATVault _vault, IHATClaimsManager.ClaimsManagerInitParams calldata _params) external initializer {
if (_params.maxBounty > MAX_BOUNTY_LIMIT && _params.maxBounty != HUNDRED_PERCENT)
revert MaxBountyCannotBeMoreThanMaxBountyLimit();
HATVaultsRegistry _registry = HATVaultsRegistry(msg.sender);
if (_params.governanceFee > _registry.MAX_GOVERNANCE_FEE() && _params.governanceFee != NULL_UINT16)
revert FeeCannotBeMoreThanMaxFee();
_validateSplit(_params.bountySplit);
_setVestingParams(_params.vestingDuration, _params.vestingPeriods);
HATVaultsRegistry _registry = HATVaultsRegistry(msg.sender);
maxBounty = _params.maxBounty;
bountySplit = _params.bountySplit;
governanceFee = _params.governanceFee;
committee = _params.committee;
registry = _registry;
vault = _vault;
Expand All @@ -140,8 +141,6 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
isTokenLockRevocable = _params.isTokenLockRevocable;

// Set vault to use default registry values where applicable
bountyGovernanceHAT = NULL_UINT16;
bountyHackerHATVested = NULL_UINT16;
challengePeriod = NULL_UINT32;
challengeTimeOutPeriod = NULL_UINT32;
}
Expand Down Expand Up @@ -176,8 +175,7 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
// solhint-disable-next-line not-rely-on-time
createdAt: uint32(block.timestamp),
challengedAt: 0,
bountyGovernanceHAT: getBountyGovernanceHAT(),
bountyHackerHATVested: getBountyHackerHATVested(),
governanceFee: getGovernanceFee(),
arbitrator: arbitratorAddress,
challengePeriod: getChallengePeriod(),
challengeTimeOutPeriod: getChallengeTimeOutPeriod(),
Expand Down Expand Up @@ -255,17 +253,12 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu

address tokenLock;

IHATClaimsManager.ClaimBounty memory claimBounty = _calcClaimBounty(
_claim.bountyPercentage,
_claim.bountyGovernanceHAT,
_claim.bountyHackerHATVested
);
IHATClaimsManager.ClaimBounty memory claimBounty = _calcClaimBounty(_claim.bountyPercentage, _claim.governanceFee);

vault.makePayout(
claimBounty.committee +
claimBounty.governanceHat +
claimBounty.governanceFee +
claimBounty.hacker +
claimBounty.hackerHatVested +
claimBounty.hackerVested
);

Expand Down Expand Up @@ -293,19 +286,7 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
_asset.safeTransfer(_claim.beneficiary, claimBounty.hacker);
_asset.safeTransfer(_claim.committee, claimBounty.committee);

// send to the registry the amount of tokens which should be swapped
// to HAT so it could call swapAndSend in a separate tx.
IHATVaultsRegistry _registry = registry;
_asset.safeApprove(address(_registry), claimBounty.hackerHatVested + claimBounty.governanceHat);
_registry.addTokensToSwap(
_asset,
_claim.beneficiary,
claimBounty.hackerHatVested,
claimBounty.governanceHat
);

// make sure to reset approval
_asset.safeApprove(address(_registry), 0);
_asset.safeTransfer(registry.governanceFeeReceiver(), claimBounty.governanceFee);

emit ApproveClaim(
_claimId,
Expand Down Expand Up @@ -400,14 +381,15 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
emit SetMaxBounty(_maxBounty);
}

/** @notice See {IHATClaimsManager-setHATBountySplit}. */
function setHATBountySplit(uint16 _bountyGovernanceHAT, uint16 _bountyHackerHATVested) external onlyRegistryOwner {
bountyGovernanceHAT = _bountyGovernanceHAT;
bountyHackerHATVested = _bountyHackerHATVested;
/** @notice See {IHATClaimsManager-setGoveranceFee}. */
function setGovernanceFee(uint16 _governanceFee) external onlyRegistryOwner {
if (_governanceFee > registry.MAX_GOVERNANCE_FEE() && _governanceFee != NULL_UINT16) {
revert FeeCannotBeMoreThanMaxFee();
}

registry.validateHATSplit(getBountyGovernanceHAT(), getBountyHackerHATVested());
governanceFee = _governanceFee;

emit SetHATBountySplit(_bountyGovernanceHAT, _bountyHackerHATVested);
emit SetGovernanceFee(_governanceFee);
}

/** @notice See {IHATClaimsManager-setArbitrator}. */
Expand Down Expand Up @@ -458,23 +440,13 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu

/* --------------------------------- Getters -------------------------------------- */

/** @notice See {IHATClaimsManager-getBountyGovernanceHAT}. */
function getBountyGovernanceHAT() public view returns(uint16) {
uint16 _bountyGovernanceHAT = bountyGovernanceHAT;
if (_bountyGovernanceHAT != NULL_UINT16) {
return _bountyGovernanceHAT;
} else {
return registry.defaultBountyGovernanceHAT();
}
}

/** @notice See {IHATClaimsManager-getBountyHackerHATVested}. */
function getBountyHackerHATVested() public view returns(uint16) {
uint16 _bountyHackerHATVested = bountyHackerHATVested;
if (_bountyHackerHATVested != NULL_UINT16) {
return _bountyHackerHATVested;
/** @notice See {IHATClaimsManager-getGovernanceFee}. */
function getGovernanceFee() public view returns(uint16) {
uint16 _getGovernanceFee = governanceFee;
if (_getGovernanceFee != NULL_UINT16) {
return _getGovernanceFee;
} else {
return registry.defaultBountyHackerHATVested();
return registry.defaultGovernanceFee();
}
}

Expand Down Expand Up @@ -531,14 +503,12 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu
* predefined bounty split and the given bounty percentage
* @param _bountyPercentage The percentage of the vault's funds to be paid
* out as bounty
* @param _bountyGovernanceHAT The bountyGovernanceHAT at the time the claim was submitted
* @param _bountyHackerHATVested The bountyHackerHATVested at the time the claim was submitted
* @param _governanceFee The governanceFee at the time the claim was submitted
* @return claimBounty The bounty distribution for this specific claim
*/
function _calcClaimBounty(
uint256 _bountyPercentage,
uint256 _bountyGovernanceHAT,
uint256 _bountyHackerHATVested
uint16 _bountyPercentage,
uint16 _governanceFee
) internal view returns(IHATClaimsManager.ClaimBounty memory claimBounty) {
uint256 _totalAssets = vault.totalAssets();
if (_totalAssets == 0) {
Expand All @@ -551,13 +521,11 @@ contract HATClaimsManager is IHATClaimsManager, OwnableUpgradeable, ReentrancyGu

uint256 _totalBountyAmount = _totalAssets * _bountyPercentage;

uint256 _governanceHatAmount = _totalBountyAmount.mulDiv(_bountyGovernanceHAT, HUNDRED_PERCENT_SQRD);
uint256 _hackerHatVestedAmount = _totalBountyAmount.mulDiv(_bountyHackerHATVested, HUNDRED_PERCENT_SQRD);
uint256 _governanceFeeAmount = _totalBountyAmount.mulDiv(_governanceFee, HUNDRED_PERCENT_SQRD);

_totalBountyAmount -= (_governanceHatAmount + _hackerHatVestedAmount) * HUNDRED_PERCENT;
_totalBountyAmount -= _governanceFeeAmount * HUNDRED_PERCENT;

claimBounty.governanceHat = _governanceHatAmount;
claimBounty.hackerHatVested = _hackerHatVestedAmount;
claimBounty.governanceFee = _governanceFeeAmount;

uint256 _hackerVestedAmount = _totalBountyAmount.mulDiv(bountySplit.hackerVested, HUNDRED_PERCENT_SQRD);
uint256 _hackerAmount = _totalBountyAmount.mulDiv(bountySplit.hacker, HUNDRED_PERCENT_SQRD);
Expand Down
19 changes: 0 additions & 19 deletions contracts/HATTimelockController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,6 @@ contract HATTimelockController is TimelockController {
_rewardController.setAllocPoint(address(_vault), _allocPoint);
}

function swapAndSend(
IHATVaultsRegistry _registry,
address _asset,
address[] calldata _beneficiaries,
uint256 _amountOutMinimum,
address _routingContract,
bytes calldata _routingPayload
)
external
onlyRole(PROPOSER_ROLE) {
_registry.swapAndSend(
_asset,
_beneficiaries,
_amountOutMinimum,
_routingContract,
_routingPayload
);
}

function setEmergencyPaused(IHATVaultsRegistry _registry, bool _isEmergencyPaused) external onlyRole(PROPOSER_ROLE) {
_registry.setEmergencyPaused(_isEmergencyPaused);
}
Expand Down
Loading

0 comments on commit e923bcc

Please sign in to comment.