Skip to content

Commit

Permalink
Merge branch 'master' into pahor/v3v4updatescript
Browse files Browse the repository at this point in the history
  • Loading branch information
pahor167 authored Nov 6, 2024
2 parents 8cc41ec + a3c350a commit d545326
Show file tree
Hide file tree
Showing 11 changed files with 609 additions and 63 deletions.
12 changes: 9 additions & 3 deletions contracts/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,12 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
* @notice Scheduling transfer was not successfull since
* total amount of "from" and "to" are not the same.
*/
error TransferAmountMisalignment();
error TransferAmountMisalignment(uint256 totalFromVotes, uint256 totalToVotes);

/**
* @notice When scheduling transfer and the from group doesn't have enough CELO.
*/
error NotEnoughCeloInGroup(address group, uint256 expectedAmount, uint256 realAmount);

/**
* @notice Empty constructor for proxy implementation, `initializer` modifer ensures the
Expand Down Expand Up @@ -288,7 +293,8 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
for (uint256 i = 0; i < fromGroups.length; i++) {
uint256 celoAvailableForGroup = getCeloForGroup(fromGroups[i]);

if (celoAvailableForGroup < fromVotes[i]) revert TransferAmountMisalignment();
if (celoAvailableForGroup < fromVotes[i])
revert NotEnoughCeloInGroup(fromGroups[i], fromVotes[i], celoAvailableForGroup);
getAndUpdateToVoteAndToRevoke(fromGroups[i], 0, fromVotes[i]);
totalFromVotes += fromVotes[i];
}
Expand All @@ -299,7 +305,7 @@ contract Account is UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Managed, I
}

if (totalFromVotes != totalToVotes) {
revert TransferAmountMisalignment();
revert TransferAmountMisalignment(totalFromVotes, totalToVotes);
}
}

Expand Down
36 changes: 24 additions & 12 deletions contracts/DefaultStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,16 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
* @return finalGroups The groups that were chosen for distribution.
* @return finalVotes The votes of chosen finalGroups.
*/
function generateDepositVoteDistribution(uint256 celoAmount, address depositGroupToIgnore)
function generateDepositVoteDistribution(
uint256 celoAmount,
uint256 stCeloAmount,
address depositGroupToIgnore
)
external
managerOrStrategy
returns (address[] memory finalGroups, uint256[] memory finalVotes)
{
return _generateDepositVoteDistribution(celoAmount, depositGroupToIgnore);
return _generateDepositVoteDistribution(celoAmount, stCeloAmount, depositGroupToIgnore);
}

/**
Expand Down Expand Up @@ -623,7 +627,7 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
uint256
)
{
return (1, 1, 1, 0);
return (1, 2, 0, 0);
}

/**
Expand Down Expand Up @@ -694,6 +698,7 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
_updateGroupStCelo(group, groupTotalStCeloVotes, false);
_generateDepositVoteDistribution(
IManager(manager).toCelo(groupTotalStCeloVotes),
groupTotalStCeloVotes,
address(0)
);
}
Expand All @@ -709,10 +714,11 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
* @return finalGroups The groups that were chosen for distribution.
* @return finalVotes The votes of chosen finalGroups.
*/
function _generateDepositVoteDistribution(uint256 celoAmount, address depositGroupToIgnore)
private
returns (address[] memory finalGroups, uint256[] memory finalVotes)
{
function _generateDepositVoteDistribution(
uint256 celoAmount,
uint256 stCeloAmount,
address depositGroupToIgnore
) private returns (address[] memory finalGroups, uint256[] memory finalVotes) {
if (activeGroups.getNumElements() == 0) {
revert NoActiveGroups();
}
Expand All @@ -735,11 +741,9 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
votes[groupsIndex] = Math.min(receivableVotes, celoAmount);
groups[groupsIndex] = votedGroup;
celoAmount -= votes[groupsIndex];
_updateGroupStCelo(
votedGroup,
IManager(manager).toStakedCelo(votes[groupsIndex]),
true
);
uint256 stCelo = IManager(manager).toStakedCelo(votes[groupsIndex]);
stCeloAmount = stCeloAmount >= stCelo ? stCeloAmount - stCelo : 0;
_updateGroupStCelo(votedGroup, stCelo, true);
trySort(votedGroup, stCeloInGroup[votedGroup], true);

if (sorted) {
Expand All @@ -754,6 +758,14 @@ contract DefaultStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausable {
revert NotAbleToDistributeVotes();
}

if (stCeloAmount != 0) {
if (votedGroup == address(0)) {
votedGroup = activeGroups.getTail();
}
_updateGroupStCelo(votedGroup, stCeloAmount, true);
trySort(votedGroup, stCeloInGroup[votedGroup], true);
}

finalGroups = new address[](groupsIndex);
finalVotes = new uint256[](groupsIndex);

Expand Down
37 changes: 30 additions & 7 deletions contracts/Manager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,18 @@ contract Manager is Errors, UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Pa
revert GroupNotEligible(newStrategy);
}

uint256 stCeloAmount = stakedCelo.balanceOf(msg.sender) +
stakedCelo.lockedVoteBalanceOf(msg.sender);
if (stCeloAmount != 0) {
_transfer(strategies[msg.sender], newStrategy, stCeloAmount);
}
_changeStrategy(msg.sender, newStrategy);
}

strategies[msg.sender] = newStrategy;
emit StrategyChanged(newStrategy);
/**
* @notice Allows owner to change strategy for account.
* address(0) = default strategy
* !address(0) = voting for validator group.
* @param _account The account to change strategy for.
* @param newStrategy The new strategy.
*/
function forceChangeStrategy(address _account, address newStrategy) public onlyOwner {
_changeStrategy(_account, newStrategy);
}

/**
Expand Down Expand Up @@ -635,6 +639,7 @@ contract Manager is Errors, UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Pa
} else {
(finalGroups, finalVotes) = defaultStrategy.generateDepositVoteDistribution(
votes,
stCeloAmount,
address(0)
);
}
Expand Down Expand Up @@ -731,6 +736,24 @@ contract Manager is Errors, UUPSOwnableUpgradeable, UsingRegistryUpgradeable, Pa
account.scheduleTransfer(fromGroups, fromVotes, toGroups, toVotes);
}

/**
* @notice Allows strategy to change strategy for account.
* address(0) = default strategy
* !address(0) = voting for validator group.
* @param _account The account to change strategy for.
* @param newStrategy The new strategy.
*/
function _changeStrategy(address _account, address newStrategy) private {
uint256 stCeloAmount = stakedCelo.balanceOf(_account) +
stakedCelo.lockedVoteBalanceOf(_account);
if (stCeloAmount != 0) {
_transfer(strategies[_account], newStrategy, stCeloAmount);
}

strategies[_account] = newStrategy;
emit StrategyChanged(newStrategy);
}

/**
* Returns votes count that can be received by group directly in Election contract.
* @param group The group that can receive votes.
Expand Down
26 changes: 15 additions & 11 deletions contracts/SpecificGroupStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,14 @@ contract SpecificGroupStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausa

celoAmount -= votesToBeScheduledForSpecificGroup;
if (celoAmount > 0) {
uint256 stCeloAmountOverflow = Math.min(
IManager(manager).toStakedCelo(celoAmount),
stCeloAmount
);
// overflow
(address[] memory groups, uint256[] memory votesForGroups) = defaultStrategy
.generateDepositVoteDistribution(celoAmount, group);
updateOverflowGroup(
group,
Math.min(IManager(manager).toStakedCelo(celoAmount), stCeloAmount),
true
);
.generateDepositVoteDistribution(celoAmount, stCeloAmountOverflow, group);
updateOverflowGroup(group, stCeloAmountOverflow, true);
finalGroups = new address[](groups.length + 1);
finalVotes = new uint256[](groups.length + 1);
for (uint256 i = 0; i < groups.length; i++) {
Expand All @@ -358,6 +358,7 @@ contract SpecificGroupStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausa
} else {
(finalGroups, finalVotes) = defaultStrategy.generateDepositVoteDistribution(
celoAmount,
stCeloAmount,
group
);
updateUnhealthyGroupStCelo(group, stCeloAmount, true);
Expand Down Expand Up @@ -391,10 +392,10 @@ contract SpecificGroupStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausa
}

uint256 overflow = stCeloInGroupOverflowed[group];
uint256 toMove = totalStCeloInGroup - unhealthyStCelo - overflow;
uint256 toMoveStCelo = totalStCeloInGroup - unhealthyStCelo - overflow;

transferToDefaultStrategy(group, toMove);
updateUnhealthyGroupStCelo(group, toMove, true);
transferToDefaultStrategy(group, toMoveStCelo);
updateUnhealthyGroupStCelo(group, toMoveStCelo, true);
}
}

Expand Down Expand Up @@ -602,13 +603,16 @@ contract SpecificGroupStrategy is Errors, UUPSOwnableUpgradeable, Managed, Pausa
* @param stCeloToMove StCelo amount to be moved.
*/
function transferToDefaultStrategy(address group, uint256 stCeloToMove) private {
uint256 toMoveCelo = IManager(manager).toCelo(stCeloToMove);
uint256 toMoveCelo = Math.min(
account.getCeloForGroup(group),
IManager(manager).toCelo(stCeloToMove)
);
address[] memory fromGroups = new address[](1);
uint256[] memory fromVotes = new uint256[](1);
fromGroups[0] = group;
fromVotes[0] = toMoveCelo;
(address[] memory toGroups, uint256[] memory toVotes) = defaultStrategy
.generateDepositVoteDistribution(toMoveCelo, address(0));
.generateDepositVoteDistribution(toMoveCelo, stCeloToMove, address(0));
IManager(manager).scheduleTransferWithinStrategy(fromGroups, toGroups, fromVotes, toVotes);
}

Expand Down
8 changes: 5 additions & 3 deletions contracts/interfaces/IDefaultStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
pragma solidity 0.8.11;

interface IDefaultStrategy {
function generateDepositVoteDistribution(uint256 celoAmount, address depositGroupToIgnore)
external
returns (address[] memory finalGroups, uint256[] memory finalVotes);
function generateDepositVoteDistribution(
uint256 celoAmount,
uint256 stCeloAmount,
address depositGroupToIgnore
) external returns (address[] memory finalGroups, uint256[] memory finalVotes);

function generateWithdrawalVoteDistribution(uint256 celoAmount)
external
Expand Down
6 changes: 3 additions & 3 deletions test-ts/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,15 +520,15 @@ describe("Account", () => {
account
.connect(manager)
.scheduleTransfer(groupAddresses, [100, 30, 80], groupAddresses, [30, 70, 100])
).revertedWith(`TransferAmountMisalignment()`);
).revertedWith(`'NotEnoughCeloInGroup("${groupAddresses[0]}", 100, 0)`);
});

it("should revert when incorrect vote sum 2", async () => {
await expect(
account
.connect(manager)
.scheduleTransfer(groupAddresses, [100, 30, 60], groupAddresses, [30, 70, 100])
).revertedWith(`TransferAmountMisalignment()`);
).revertedWith(`NotEnoughCeloInGroup("${groupAddresses[0]}", 100, 0)`);
});

describe("When group has activated votes", () => {
Expand Down Expand Up @@ -645,7 +645,7 @@ describe("Account", () => {
[groupAddresses[1]],
[originalGroupAmount * 2]
)
).revertedWith(`TransferAmountMisalignment()`);
).revertedWith(`NotEnoughCeloInGroup("${groupAddresses[0]}", 200, 100)`);
});
});

Expand Down
2 changes: 1 addition & 1 deletion test-ts/default-strategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ describe("DefaultStrategy", () => {
await expect(
defaultStrategyContract
.connect(nonManager)
.generateDepositVoteDistribution(10, ADDRESS_ZERO)
.generateDepositVoteDistribution(10, 10, ADDRESS_ZERO)
).revertedWith(`CallerNotManagerNorStrategy("${nonManager.address}")`);
});
});
Expand Down
Loading

0 comments on commit d545326

Please sign in to comment.