Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contracts): unbond validator KRO #351

Merged
merged 7 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 105 additions & 115 deletions packages/contracts/contracts/L1/AssetManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
}

/**
* @inheritdoc IAssetManager
* @inheritdoc IAssetManager
*/
function getKghReward(
address validator,
Expand Down Expand Up @@ -689,18 +689,34 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
* @param validator Address of the validator.
*/
function bondValidatorKro(address validator) external onlyValidatorManager {
Vault storage vault = _vaults[validator];
if (vault.asset.validatorKro - vault.asset.validatorKroBonded < BOND_AMOUNT)
revert InsufficientAsset();
Asset storage asset = _vaults[validator].asset;
uint128 remainder = asset.validatorKro - asset.validatorKroBonded;
if (remainder < BOND_AMOUNT) revert InsufficientAsset();

unchecked {
vault.asset.validatorKroBonded += BOND_AMOUNT;
asset.validatorKroBonded += BOND_AMOUNT;
}

emit ValidatorKroBonded(
emit ValidatorKroBonded(validator, BOND_AMOUNT, remainder - BOND_AMOUNT);
}

/**
* @notice Unbond KRO from validator KRO during output finalization or challenge slashing. This
* function is only called by the ValidatorManager contract.
*
* @param validator Address of the validator.
*/
function unbondValidatorKro(address validator) external onlyValidatorManager {
Asset storage asset = _vaults[validator].asset;

unchecked {
asset.validatorKroBonded -= BOND_AMOUNT;
}

emit ValidatorKroUnbonded(
validator,
BOND_AMOUNT,
vault.asset.validatorKro - vault.asset.validatorKroBonded
asset.validatorKro - asset.validatorKroBonded
);
}

Expand All @@ -726,119 +742,96 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
baseReward + boostedReward + validatorReward
);
} else {
Vault storage vault = _vaults[validator];
Asset storage asset = _vaults[validator].asset;
unchecked {
vault.asset.totalKro += baseReward;
asset.totalKro += baseReward;
// TODO: handle reward for boosted reward
asset.validatorKroBonded -= BOND_AMOUNT;
}

emit ValidatorKroUnbonded(
validator,
BOND_AMOUNT,
asset.validatorKro - asset.validatorKroBonded
);
}

// TODO - Distribute the reward from a designated vault to the AssetManager contract.
}

/**
* @notice Modify the balance of the vault during challenge. This function is only called by the
* ValidatorManager contract.
* @notice Update the vault of challenge winner with the challenge reward. This function is only
* called by the ValidatorManager contract.
*
* @param validator Address of the validator.
* @param challengeReward The challenge reward to be added to the winner's asset. If 0, the
* challenge reward which will be slashed from loser's asset is
* determined in this function.
* @param isLoser True if the given validator is the loser at the challenge.
* @param winner Address of the challenge winner.
* @param challengeReward The challenge reward to be added to the winner's asset after excluding
* tax.
*
* @return The tax amount.
* @return The challenge reward to be added to the winner's asset.
* @return The challenge reward added to winner's asset.
*/
// TODO: change this according to the new design regarding to bond
function modifyBalanceWithChallenge(
address validator,
uint128 challengeReward,
bool isLoser
) external onlyValidatorManager returns (uint128, uint128) {
Vault storage vault = _vaults[validator];

uint128 totalAmount = vault.asset.totalKro +
vault.pending.totalPendingAssets +
vault.pending.totalPendingBoostedRewards +
vault.asset.validatorRewardKro +
vault.pending.totalPendingValidatorRewards +
vault.asset.boostedReward -
vault.asset.totalKroInKgh;

uint128[6] memory arr = [
(vault.asset.totalKro - vault.asset.totalKroInKgh),
vault.asset.boostedReward,
vault.pending.totalPendingAssets,
vault.pending.totalPendingBoostedRewards,
vault.asset.validatorRewardKro,
vault.pending.totalPendingValidatorRewards
];

if (isLoser) {
challengeReward = totalAmount.mulDiv(SLASHING_RATE, SLASHING_RATE_DENOM); // TODO
challengeReward = challengeReward > MIN_SLASHING_AMOUNT
? challengeReward
: MIN_SLASHING_AMOUNT;
function increaseBalanceWithChallenge(
address winner,
uint128 challengeReward
) external onlyValidatorManager returns (uint128) {
Asset storage asset = _vaults[winner].asset;

// If challenge reward is distributed to SECURITY_COUNCIL, transfer it directly.
if (winner == SECURITY_COUNCIL) {
ASSET_TOKEN.safeTransfer(SECURITY_COUNCIL, challengeReward);
return;
}

unchecked {
// Since validatorKro is included in totalKro, it does not need to be included in
// totalAmount calculation, but we should update this value as well.
vault.asset.validatorKro -= vault.asset.validatorKro.mulDiv(
challengeReward,
totalAmount
);
uint128 tax = challengeReward.mulDiv(TAX_NUMERATOR, TAX_DENOMINATOR);
ASSET_TOKEN.safeTransfer(SECURITY_COUNCIL, tax);

vault.asset.totalKro -= arr[0].mulDiv(challengeReward, totalAmount);
vault.asset.boostedReward -= arr[1].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingAssets -= arr[2].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingBoostedRewards -= arr[3].mulDiv(
challengeReward,
totalAmount
);
vault.asset.validatorRewardKro -= arr[4].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingValidatorRewards -= arr[5].mulDiv(
challengeReward,
totalAmount
);
}
unchecked {
challengeReward -= tax;
asset.validatorKro += challengeReward;
}

uint128 tax = challengeReward.mulDiv(TAX_NUMERATOR, TAX_DENOMINATOR);
unchecked {
challengeReward -= tax;
}
return challengeReward;
}

ASSET_TOKEN.safeTransfer(SECURITY_COUNCIL, tax);
/**
* @notice Update the vault of challenge loser with the challenge reward. This function is only
* called by the ValidatorManager contract.
*
* @param loser Address of the challenge loser.
*
* @return The challenge reward slashed from loser's asset.
*/
function decreaseBalanceWithChallenge(
address loser
) external onlyValidatorManager returns (uint128) {
Asset storage asset = _vaults[loser].asset;

return (tax, challengeReward);
} else {
// If challenge reward is distributed to SECURITY_COUNCIL, transfer it directly.
if (validator == SECURITY_COUNCIL) {
ASSET_TOKEN.safeTransfer(SECURITY_COUNCIL, challengeReward);
return (0, challengeReward);
}
unchecked {
asset.validatorKroBonded -= BOND_AMOUNT;
asset.validatorKro -= BOND_AMOUNT;
}

unchecked {
vault.asset.validatorKro += vault.asset.validatorKro.mulDiv(
challengeReward,
totalAmount
);
return BOND_AMOUNT;
}

vault.asset.totalKro += arr[0].mulDiv(challengeReward, totalAmount);
vault.asset.boostedReward += arr[1].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingAssets += arr[2].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingBoostedRewards += arr[3].mulDiv(
challengeReward,
totalAmount
);
vault.asset.validatorRewardKro += arr[4].mulDiv(challengeReward, totalAmount);
vault.pending.totalPendingValidatorRewards += arr[5].mulDiv(
challengeReward,
totalAmount
);
}
/**
* @notice Revert the changes of decreaseBalanceWithChallenge. This function is only called by
* the ValidatorManager contract.
*
* @param loser Address of the challenge original loser.
*
* @return The challenge reward refunded to loser's asset.
*/
function revertDecreaseBalanceWithChallenge(
address loser
) external onlyValidatorManager returns (uint128) {
Asset storage asset = _vaults[loser].asset;

return (0, challengeReward);
unchecked {
asset.validatorKroBonded += BOND_AMOUNT;
asset.validatorKro += BOND_AMOUNT;
}

return BOND_AMOUNT;
}

/**
Expand Down Expand Up @@ -959,11 +952,11 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
* @param updateTree Flag to update the validator tree.
*/
function _deposit(address validator, uint128 assets, bool updateTree) internal {
Vault storage vault = _vaults[validator];
Asset storage asset = _vaults[validator].asset;
ASSET_TOKEN.safeTransferFrom(validator, address(this), assets);

unchecked {
vault.asset.validatorKro += assets;
asset.validatorKro += assets;
}

if (updateTree) {
Expand All @@ -975,14 +968,14 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
* @notice Internal function to delegate KRO to the validator.
*
* @param validator Address of the validator.
* @param owner Address of the delegator.
* @param delegator Address of the delegator.
* @param assets The amount of KRO to delegate.
*
* @return The amount of shares that the Vault would exchange for the amount of assets provided.
*/
function _delegate(
address validator,
address owner,
address delegator,
uint128 assets
) internal returns (uint128) {
uint128 shares = _convertToKroShares(validator, assets);
Expand All @@ -991,7 +984,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
unchecked {
vault.asset.totalKro += assets;
vault.asset.totalKroShares += shares;
vault.kroDelegators[owner].shares += shares;
vault.kroDelegators[delegator].shares += shares;
}

VALIDATOR_MANAGER.updateValidatorTree(validator, false);
Expand Down Expand Up @@ -1063,21 +1056,21 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
* @notice Internal function to undelegate KRO from the validator.
*
* @param validator Address of the validator.
* @param owner Address of the delegator.
* @param delegator Address of the delegator.
* @param assets The amount of KRO to undelegate.
* @param shares The amount of shares to undelegate.
*/
function _initUndelegate(
address validator,
address owner,
address delegator,
uint128 assets,
uint128 shares
) internal {
Vault storage vault = _vaults[validator];

unchecked {
vault.asset.totalKroShares -= shares;
vault.kroDelegators[owner].shares -= shares;
vault.kroDelegators[delegator].shares -= shares;

vault.asset.totalKro -= assets;
_addPendingKroShares(vault, assets, shares);
Expand All @@ -1090,21 +1083,21 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
* @notice Internal function to undelegate KGH from the validator.
*
* @param validator Address of the validator.
* @param owner Address of the delegator.
* @param delegator Address of the delegator.
* @param tokenId Token Id of the KGH.
* @param kroShares The amount of KRO shares to undelegate.
* @param kghShares The amount of KGH shares to undelegate.
*/
function _initUndelegateKgh(
address validator,
address owner,
address delegator,
uint256 tokenId,
uint128 kroShares,
uint128 kghShares
) internal {
Vault storage vault = _vaults[validator];
uint128 kroAssetsToWithdraw = _convertToKroAssets(validator, kroShares);
uint128 kghAssetsToWithdraw = _convertToKghAssets(validator, owner, tokenId);
uint128 kghAssetsToWithdraw = _convertToKghAssets(validator, delegator, tokenId);
uint128 boostedRewardsToReceive;

uint256[] memory tokenIds = new uint256[](1);
Expand All @@ -1113,7 +1106,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
unchecked {
vault.asset.totalKroShares -= kroShares;
vault.asset.totalKghShares -= kghShares;
delete vault.kghDelegators[owner].shares[tokenId];
delete vault.kghDelegators[delegator].shares[tokenId];

uint128 kroInKgh = KGH_MANAGER.totalKroInKgh(tokenId);
uint128 baseRewardsToReceive = kroAssetsToWithdraw - kroInKgh;
Expand Down Expand Up @@ -1204,10 +1197,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager {
*
* @return The amount of the claimed boosted reward.
*/
function _claimBoostedReward(
address validator,
address delegator,
) internal returns (uint128) {
function _claimBoostedReward(address validator, address delegator) internal returns (uint128) {
Vault storage vault = _vaults[validator];
KghDelegator storage kghDelegator = vault.kghDelegators[delegator];

Expand Down
Loading
Loading