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

E2E EpochManager test + Epoch truffle migrations & Anvil L2 migration build fix #11198

Merged
merged 76 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
f9979ce
unit test with mocks
soloseng Aug 19, 2024
75bf938
++ integration tests
soloseng Aug 20, 2024
cb47ec9
clean up
soloseng Aug 20, 2024
fbdc5fd
Merge branch 'feat/l2-epoch-system' into soloseng/startNextEpochProce…
soloseng Aug 20, 2024
b8f5584
-- logging
soloseng Aug 20, 2024
282ef91
removed duplicate interface
soloseng Aug 20, 2024
40711cb
using `MockCeloToken` to get test to pass.
soloseng Aug 20, 2024
654b279
removed endEpochTimestamp
soloseng Aug 20, 2024
2072107
moved IEpochManager to 0.5 folder
soloseng Aug 20, 2024
9a6c01f
added L2 conditions for EpochRewards functions using precompiles
soloseng Aug 20, 2024
c48b8e5
renamed EpochManagerInitializer due to name conflict
soloseng Aug 21, 2024
47f93af
++ more unit test
soloseng Aug 21, 2024
d3b1db4
setup anvil migration
soloseng Aug 22, 2024
a6e2844
Merge branch 'feat/l2-epoch-system' into soloseng/startNextEpochProce…
soloseng Aug 26, 2024
2ba9360
compiles
soloseng Aug 26, 2024
35b637a
++ require fund in unreleased treasury
soloseng Aug 27, 2024
c02c0a4
Updated regex
soloseng Aug 27, 2024
92ac7cf
++ registry 0.8 for testing only
soloseng Aug 27, 2024
f50ac8b
clean up
soloseng Aug 27, 2024
3aa816c
++ unit test
soloseng Aug 27, 2024
180162b
initial integration test using L1 devchain
soloseng Aug 27, 2024
22946ff
++ comment
soloseng Aug 27, 2024
0ed7e93
-- forge based integration test
soloseng Aug 27, 2024
7fcc9a8
Merge branch 'feat/l2-epoch-system' into soloseng/startNextEpochProce…
soloseng Aug 27, 2024
8f0ea64
++ to const
soloseng Aug 27, 2024
cfa7cdb
happy linter
soloseng Aug 28, 2024
cdf7aea
update contract name
soloseng Aug 28, 2024
4b709d3
Adding truffle migrations
pahor167 Aug 29, 2024
969f9d3
Fix of L2 Anvil migrations
pahor167 Aug 29, 2024
8838c5c
Improved anvil devchain compilation
pahor167 Aug 29, 2024
93274c8
Release init params
pahor167 Aug 29, 2024
b49f929
++ PR feedback
soloseng Aug 29, 2024
1b616ca
++ checks
soloseng Sep 10, 2024
b47dba3
updated carbon address
soloseng Sep 10, 2024
f34e7e0
E2E test
pahor167 Sep 11, 2024
a050d27
lint
pahor167 Sep 11, 2024
0e8da38
Merge branch 'soloseng/startNextEpochProcess-unit-and-integration-tes…
pahor167 Sep 11, 2024
48db871
proxy stableToken mint call via Validators contract
soloseng Sep 11, 2024
8a8f4d9
Merge branch 'feat/l2-epoch-system' into soloseng/startNextEpochProce…
soloseng Sep 11, 2024
bbb239f
-- duplicate imports
soloseng Sep 11, 2024
2ffeed2
removed registry08. replaced with vm call
soloseng Sep 11, 2024
b195ebb
PR feedback
soloseng Sep 11, 2024
e84a5b5
generate Ecdsa Pub Key dynamically in migration.s.sol
pahor167 Sep 12, 2024
3c2ebfc
-- coment
soloseng Sep 12, 2024
83bd5aa
passing unit tests
soloseng Sep 12, 2024
1d4eaa4
clean up
soloseng Sep 12, 2024
43ae993
++ mintStable test
soloseng Sep 12, 2024
de06b4e
-- TODO; compiles test when filtering
soloseng Sep 12, 2024
15a5290
E2E test with 3 groups with 2 validators each
pahor167 Sep 13, 2024
84f4349
fix for rewards computation
pahor167 Sep 13, 2024
17c5884
lint
pahor167 Sep 13, 2024
bc53164
merge
pahor167 Sep 13, 2024
9ddb522
anvil migration rename
pahor167 Sep 13, 2024
48cf98c
remove setEpochMangerEnabler
pahor167 Sep 13, 2024
28bf1ff
truffle build fix
pahor167 Sep 16, 2024
e5ffbf1
initializeEpochManagerSystem
pahor167 Sep 16, 2024
96363fc
migration test fix
pahor167 Sep 16, 2024
812604d
prettify
pahor167 Sep 16, 2024
abdbae4
removal of logging
pahor167 Sep 16, 2024
55bd69b
removal of logging2
pahor167 Sep 16, 2024
fe91831
EpochManagerEnabler version
pahor167 Sep 12, 2024
2c5a95f
Enable epoch manager in devchain
pahor167 Sep 16, 2024
13510fd
lint
pahor167 Sep 16, 2024
eb5691b
Merge branch 'feat/l2-epoch-system' into pahor/truffleMigrations
martinvol Sep 17, 2024
6011483
Rolled back contracts/identity/FederatedAttestations.sol added by mis…
martinvol Sep 17, 2024
776f864
removed duplicated function
martinvol Sep 17, 2024
a152a09
Fix tests
martinvol Sep 17, 2024
f5a2cb8
lint
martinvol Sep 17, 2024
95a6b65
Fixed tests and moved ValidatorsMock08 to solidity test folder
martinvol Sep 17, 2024
69b3bd8
Added release data
martinvol Sep 17, 2024
f477f74
Deleted prints in release script
martinvol Sep 17, 2024
4093393
Removed unnecesary mocking
martinvol Sep 17, 2024
fc278cb
Force compilation of validator
martinvol Sep 17, 2024
5bf0d85
moved mocks to right path
martinvol Sep 17, 2024
df7a9e8
Fixed tests
martinvol Sep 17, 2024
1d62d5f
Added ScoreManager to releaseData/initializationData/release12.json
martinvol Sep 17, 2024
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
13 changes: 12 additions & 1 deletion packages/protocol/contractPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,24 @@ export const SOLIDITY_08_PACKAGE = {
proxiesPath: '/', // Proxies are still with 0.5 contracts
// Proxies shouldn't have to be added to a list manually
// https://github.com/celo-org/celo-monorepo/issues/10555
contracts: ['GasPriceMinimum', 'FeeCurrencyDirectory', 'CeloUnreleasedTreasure', 'Validators'],
contracts: [
'GasPriceMinimum',
'FeeCurrencyDirectory',
'CeloUnreleasedTreasure',
'Validators',
'EpochManager',
'EpochManagerEnabler',
'ScoreManager',
],
proxyContracts: [
'GasPriceMinimumProxy',
'FeeCurrencyDirectoryProxy',
'MentoFeeCurrencyAdapterV1',
'CeloUnreleasedTreasureProxy',
'ValidatorsProxy',
'EpochManagerProxy',
'EpochManagerEnablerProxy',
'ScoreManagerProxy',
],
truffleConfig: 'truffle-config0.8.js',
} satisfies ContractPackage
43 changes: 29 additions & 14 deletions packages/protocol/contracts-0.8/common/EpochManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,14 @@ contract EpochManager is
uint256 private currentEpochNumber;
address[] public elected;

struct ProcessedGroup {
bool processed;
uint256 epochRewards;
}

// TODO this should be able to get deleted easily
Copy link
Contributor

Choose a reason for hiding this comment

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

is this TODO still required?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

can be removed

// maybe even having it in a stadalone contract
mapping(address => bool) public processedGroups;
mapping(address => ProcessedGroup) public processedGroups;

EpochProcessState public epochProcessing;
mapping(uint256 => Epoch) private epochs;
Expand Down Expand Up @@ -181,6 +186,7 @@ contract EpochManager is
// TODO complete this function
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these TODO still required?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

can be removed

require(isOnEpochProcess(), "Epoch process is not started");
// finalize epoch
// TODO last block should be the block before and timestamp from previous block
epochs[currentEpochNumber].lastBlock = block.number - 1;
// start new epoch
currentEpochNumber++;
Expand All @@ -189,27 +195,36 @@ contract EpochManager is

for (uint i = 0; i < elected.length; i++) {
address group = getValidators().getValidatorsGroup(elected[i]);
if (!processedGroups[group]) {
if (!processedGroups[group].processed) {
epochProcessing.toProcessGroups++;
processedGroups[group] = true;
uint256 groupScore = getScoreReader().getGroupScore(group);
// We need to precompute epoch rewards for each group since computation depends on total active votes for all groups.
uint256 epochRewards = getElection().getGroupEpochRewards(
group,
epochProcessing.totalRewardsVoter,
groupScore
);
processedGroups[group] = ProcessedGroup(true, epochRewards);
}
}

require(epochProcessing.toProcessGroups == groups.length, "number of groups does not match");

for (uint i = 0; i < groups.length; i++) {
// since we are adding values it makes sense to start from the end
martinvol marked this conversation as resolved.
Show resolved Hide resolved
for (uint ii = groups.length; ii > 0; ii--) {
uint256 i = ii - 1;
ProcessedGroup storage processedGroup = processedGroups[groups[i]];
// checks that group is actually from elected group
require(processedGroups[groups[i]], "group not processed");
// by doing this, we avoid processing a group twice
delete processedGroups[groups[i]];
// TODO what happens to uptime?
uint256 groupScore = getScoreReader().getGroupScore(groups[i]);
uint256 epochRewards = getElection().getGroupEpochRewards(
require(processedGroup.processed, "group not processed");
getElection().distributeEpochRewards(
groups[i],
epochProcessing.totalRewardsVoter,
groupScore
processedGroup.epochRewards,
lessers[i],
greaters[i]
);
getElection().distributeEpochRewards(groups[i], epochRewards, lessers[i], greaters[i]);

// by doing this, we avoid processing a group twice
delete processedGroups[groups[i]];
}
getCeloUnreleasedTreasure().release(
registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID),
Expand All @@ -220,7 +235,7 @@ contract EpochManager is
epochProcessing.totalRewardsCarbonFund
);
// run elections
elected = getElection().electNValidatorSigners(10, 20);
elected = getElection().electValidatorSigners();
// TODO check how to nullify stuct
epochProcessing.status = EpochProcessStatus.NotStarted;
}
Expand Down
17 changes: 15 additions & 2 deletions packages/protocol/contracts-0.8/common/EpochManagerEnabler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "../../contracts/governance/interfaces/IEpochRewards.sol";

contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
uint256 public lastKnownEpochNumber;
uint256 public lastKnownFirstBlockOfEpoch;
address[] public lastKnownElectedAccounts;

/**
Expand All @@ -33,10 +34,11 @@ contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
*/
function initEpochManager() external onlyL2 {
require(lastKnownEpochNumber != 0, "lastKnownEpochNumber not set.");
require(lastKnownFirstBlockOfEpoch != 0, "lastKnownFirstBlockOfEpoch not set.");
require(lastKnownElectedAccounts.length > 0, "lastKnownElectedAccounts not set.");
getEpochManager().initializeSystem(
lastKnownEpochNumber,
_getFirstBlockOfEpoch(lastKnownEpochNumber),
lastKnownFirstBlockOfEpoch,
lastKnownElectedAccounts
);
}
Expand All @@ -48,8 +50,8 @@ contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
lastKnownEpochNumber = getEpochNumber();

uint256 numberElectedValidators = numberValidatorsInCurrentSet();

lastKnownElectedAccounts = new address[](numberElectedValidators);
lastKnownFirstBlockOfEpoch = _getFirstBlockOfEpoch(lastKnownEpochNumber);

for (uint256 i = 0; i < numberElectedValidators; i++) {
// TODO: document how much gas this takes for 110 signers
Expand All @@ -60,6 +62,17 @@ contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
}
}

/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
* @return Major version of the contract.
* @return Minor version of the contract.
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {
return (1, 1, 0, 0);
}

function getFirstBlockOfEpoch(uint256 currentEpoch) external view returns (uint256) {
return _getFirstBlockOfEpoch(currentEpoch);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;

interface IScoreManager {
function setGroupScore(address group, uint256 score) external;
function setValidatorScore(address validator, uint256 score) external;
function getValidatorScore(address validator) external view returns (uint256);
function getGroupScore(address validator) external view returns (uint256);
function owner() external view returns (address);
}
3 changes: 0 additions & 3 deletions packages/protocol/contracts-0.8/common/test/MockCeloToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,4 @@ contract MockCeloToken08 {
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function allocatedSupply() public view returns (uint256) {
return CELO_SUPPLY_CAP - L2_INITIAL_STASH_BALANCE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,12 @@ contract MockEpochManager is IEpochManager {
function getElected() external view returns (address[] memory) {
return elected;
}

function getEpochProcessingState()
external
view
returns (uint256, uint256, uint256, uint256, uint256)
{
return (0, 0, 0, 0, 0);
}
}
20 changes: 19 additions & 1 deletion packages/protocol/contracts-0.8/governance/Validators.sol
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ contract Validators is
_;
}

modifier onlyEpochManager() {
require(msg.sender == address(getEpochManager()), "Only epoch manager can call");
_;
}

/**
* @notice Sets initialized == true on implementation contracts
* @param test Set to true to skip implementation initialization
Expand Down Expand Up @@ -514,7 +519,7 @@ contract Validators is
}

/**
* @notice Adds the first member to a group's list of members and marks it eligible for election.
* @notice Adds the first member to a group's list of members and marks the group eligible for election.
* @param validator The validator to add to the group
* @param lesser The address of the group that has received fewer votes than this group.
* @param greater The address of the group that has received more votes than this group.
Expand Down Expand Up @@ -647,6 +652,19 @@ contract Validators is
group.slashInfo.lastSlashed = block.timestamp;
}

function mintStableToEpochManager(
uint256 amount
) external onlyL2 nonReentrant onlyRegisteredContract(EPOCH_MANAGER_REGISTRY_ID) {
require(amount > 0, "mint amount is zero.");
require(
IStableToken(getStableToken()).mint(
registry.getAddressForOrDie(EPOCH_MANAGER_REGISTRY_ID),
amount
),
"mint failed to epoch manager"
);
}

/**
* @notice Allows the EpochManager contract to mint stable token for itself.
* @param amount The amount to be minted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ interface IEpochManager {
function getElected() external view returns (address[] memory);
function epochManagerEnabler() external view returns (address);
function epochDuration() external view returns (uint256);
function firstKnownEpoch() external view returns (uint256);
function getEpochProcessingState()
external
view
returns (uint256, uint256, uint256, uint256, uint256);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pragma solidity ^0.5.13;

import "../Proxy.sol";

/* solhint-disable-next-line no-empty-blocks */
contract EpochManagerEnablerProxy is Proxy {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pragma solidity ^0.5.13;

import "../Proxy.sol";

/* solhint-disable-next-line no-empty-blocks */
contract EpochManagerProxy is Proxy {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pragma solidity ^0.5.13;

import "../Proxy.sol";

/* solhint-disable-next-line no-empty-blocks */
contract ScoreManagerProxy is Proxy {}
2 changes: 1 addition & 1 deletion packages/protocol/contracts/governance/Election.sol
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ contract Election is
uint256 value,
address lesser,
address greater
) internal onlyL1 {
) internal {
if (votes.total.eligible.contains(group)) {
uint256 newVoteTotal = votes.total.eligible.getValue(group).add(value);
votes.total.eligible.update(group, newVoteTotal, lesser, greater);
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fs_permissions = [
]

[profile.devchain] # Special profile for the tests that require an anvil devchain
test = 'test-sol/devchain'
match_path = "**/test-sol/devchain/**"
no_match_path = "{**/test/BLS12Passthrough.sol,**/test/RandomTest.sol}"

Expand Down
46 changes: 26 additions & 20 deletions packages/protocol/lib/proxy-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,33 @@ export async function setAndInitializeImplementation(
},
...args: any[]
) {
const callData = web3.eth.abi.encodeFunctionCall(initializerAbi, args)
if (txOptions.from != null) {
// The proxied contract needs to be funded prior to initialization
if (txOptions.value != null) {
// Proxy's fallback fn expects the contract's implementation to be set already
// So we set the implementation first, send the funding, and then set and initialize again.
await retryTx(proxy._setImplementation, [implementationAddress, { from: txOptions.from }])
await retryTx(web3.eth.sendTransaction, [
{
from: txOptions.from,
to: proxy.address,
value: txOptions.value,
},
try {


const callData = web3.eth.abi.encodeFunctionCall(initializerAbi, args)
if (txOptions.from != null) {
// The proxied contract needs to be funded prior to initialization
if (txOptions.value != null) {
// Proxy's fallback fn expects the contract's implementation to be set already
// So we set the implementation first, send the funding, and then set and initialize again.
await retryTx(proxy._setImplementation, [implementationAddress, { from: txOptions.from }])
await retryTx(web3.eth.sendTransaction, [
{
from: txOptions.from,
to: proxy.address,
value: txOptions.value,
},
])
}
return retryTx(proxy._setAndInitializeImplementation, [
implementationAddress,
callData as any,
{ from: txOptions.from },
])
} else {
return retryTx(proxy._setAndInitializeImplementation, [implementationAddress, callData as any])
}
return retryTx(proxy._setAndInitializeImplementation, [
implementationAddress,
callData as any,
{ from: txOptions.from },
])
} else {
return retryTx(proxy._setAndInitializeImplementation, [implementationAddress, callData as any])
} catch (error) {
console.log("errror", error);
}
}
6 changes: 6 additions & 0 deletions packages/protocol/lib/web3-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ export async function _setInitialProxyImplementation<
return receipt.tx
}

export const getProxiedContract = async (contractName: string, contractPackage: ContractPackage) => {
const artifactsObject = ArtifactsSingleton.getInstance(contractPackage, artifacts)
/* eslint-disable-next-line */
return await getDeployedProxiedContract(contractName, artifactsObject)
}

export async function getDeployedProxiedContract<ContractInstance extends Truffle.ContractInstance>(
contractName: string,
customArtifacts: any
Expand Down
7 changes: 7 additions & 0 deletions packages/protocol/migrationsConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ const DefaultConfig = {
carbonOffsettingFraction: 1 / 1000,
frozen: false,
},
epochManager: {
newEpochDuration: 100,
carbonOffsettingPartner: '0x0000000000000000000000000000000000000000',
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
},
exchange: {
spread: 5 / 1000,
reserveFraction: 1 / 100,
Expand Down Expand Up @@ -165,6 +169,9 @@ const DefaultConfig = {
numRequiredConfirmations: 1,
numInternalRequiredConfirmations: 1,
},
scoreManager: {
newEpochDuration: 100,
},
stableToken: {
decimals: 18,
goldPrice: 1,
Expand Down
3 changes: 2 additions & 1 deletion packages/protocol/migrations_sol/Migration.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1131,10 +1131,11 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
bytes16(0x05050505050505050505050505050506),
bytes16(0x06060606060606060606060606060607)
);

(bytes memory ecdsaPubKey, , , ) = _generateEcdsaPubKeyWithSigner(accountAddress, validatorKey);
getValidators().registerValidator(ecdsaPubKey, newBlsPublicKey, newBlsPop);
getValidators().affiliate(groupToAffiliate);
console.log("Done registering validatora");
console.log("Done registering validators");

vm.stopBroadcast();
return accountAddress;
Expand Down
Loading
Loading