Skip to content

Commit

Permalink
Merge pull request #374 from kroma-network/feat/implement-validator-s…
Browse files Browse the repository at this point in the history
…ystem-v2

feat: implement KRO-based validator system
  • Loading branch information
seolaoh authored Aug 23, 2024
2 parents bc896c5 + 75ae796 commit 87fc8ab
Show file tree
Hide file tree
Showing 94 changed files with 17,668 additions and 2,320 deletions.
2 changes: 2 additions & 0 deletions kroma-bindings/artifacts.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"SystemConfig",
"TimeLock",
"UpgradeGovernor",
"AssetManager",
"ValidatorManager",
"ValidatorPool",
"ValidatorRewardVault",
"WETH9",
Expand Down
3,071 changes: 3,071 additions & 0 deletions kroma-bindings/bindings/assetmanager.go

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions kroma-bindings/bindings/assetmanager_more.go

Large diffs are not rendered by default.

292 changes: 235 additions & 57 deletions kroma-bindings/bindings/colosseum.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions kroma-bindings/bindings/colosseum_more.go

Large diffs are not rendered by default.

151 changes: 137 additions & 14 deletions kroma-bindings/bindings/l2outputoracle.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions kroma-bindings/bindings/l2outputoracle_more.go

Large diffs are not rendered by default.

3,004 changes: 3,004 additions & 0 deletions kroma-bindings/bindings/validatormanager.go

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions kroma-bindings/bindings/validatormanager_more.go

Large diffs are not rendered by default.

70 changes: 66 additions & 4 deletions kroma-bindings/bindings/validatorpool.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion kroma-bindings/bindings/validatorpool_more.go

Large diffs are not rendered by default.

101 changes: 93 additions & 8 deletions kroma-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ type DeployConfig struct {
GovernanceTokenOwner common.Address `json:"governanceTokenOwner"`
[Kroma: END] */
// [Kroma: START]
// GovernanceTokenAddress represents GovernanceToken address on L2.
GovernanceTokenAddress common.Address `json:"governanceTokenAddress,omitempty"`
// GovernanceTokenNotUseCreate2 is used to determine whether not to use CREATE2 to deploy GovernanceTokenProxy.
GovernanceTokenNotUseCreate2 bool `json:"governanceTokenNotUseCreate2,omitempty"`
// GovernanceTokenProxySalt is used to determine GovernanceTokenProxy address on L1 and L2.
GovernanceTokenProxySalt common.Hash `json:"governanceTokenProxySalt"`
// MintManagerOwner represents the owner of the MintManager on L1 and L2. Has the ability to mint initially.
Expand Down Expand Up @@ -273,6 +273,40 @@ type DeployConfig struct {
ValidatorPoolRequiredBondAmount *hexutil.Big `json:"validatorPoolRequiredBondAmount"`
ValidatorPoolMaxUnbond uint64 `json:"validatorPoolMaxUnbond"`
ValidatorPoolRoundDuration uint64 `json:"validatorPoolRoundDuration"`
// ValidatorPoolTerminateOutputIndex is the output index where ValidatorPool is terminated after
// in hex value.
ValidatorPoolTerminateOutputIndex *hexutil.Big `json:"validatorPoolTerminateOutputIndex"`

// ValidatorManagerTrustedValidator represents the address of the trusted validator.
ValidatorManagerTrustedValidator common.Address `json:"validatorManagerTrustedValidator"`
// ValidatorManagerMinRegisterAmount is the amount of the minimum register amount.
ValidatorManagerMinRegisterAmount *hexutil.Big `json:"validatorManagerMinRegisterAmount"`
// ValidatorManagerMinActivateAmount is the amount of the minimum activation amount.
ValidatorManagerMinActivateAmount *hexutil.Big `json:"validatorManagerMinActivateAmount"`
// ValidatorManagerCommissionChangeDelaySeconds is the delay to finalize the commission rate change in seconds.
ValidatorManagerCommissionChangeDelaySeconds uint64 `json:"validatorManagerCommissionChangeDelaySeconds"`
// ValidatorManagerRoundDurationSeconds is the duration of one submission round in seconds.
ValidatorManagerRoundDurationSeconds uint64 `json:"validatorManagerRoundDurationSeconds"`
// ValidatorManagerSoftJailPeriodSeconds is the duration of jail period in seconds in output non-submissions penalty.
ValidatorManagerSoftJailPeriodSeconds uint64 `json:"validatorManagerSoftJailPeriodSeconds"`
// ValidatorManagerHardJailPeriodSeconds is the duration of jail period in seconds in slashing penalty.
ValidatorManagerHardJailPeriodSeconds uint64 `json:"validatorManagerHardJailPeriodSeconds"`
// ValidatorManagerJailThreshold is the threshold of output non-submission to be jailed.
ValidatorManagerJailThreshold uint64 `json:"validatorManagerJailThreshold"`
// ValidatorManagerMaxFinalizations is the max number of output finalizations when distributing
// reward.
ValidatorManagerMaxFinalizations uint64 `json:"validatorManagerMaxFinalizations"`
// ValidatorManagerBaseReward is the amount of the base reward in hex value.
ValidatorManagerBaseReward *hexutil.Big `json:"validatorManagerBaseReward"`

// AssetManagerKgh represents the address of the KGH NFT contract.
AssetManagerKgh common.Address `json:"assetManagerKgh"`
// AssetManagerVault represents the address of the validator reward vault.
AssetManagerVault common.Address `json:"assetManagerVault"`
// AssetManagerMinDelegationPeriod is the duration of minimum delegation period in seconds.
AssetManagerMinDelegationPeriod uint64 `json:"assetManagerMinDelegationPeriod"`
// AssetManagerBondAmount is the bond amount.
AssetManagerBondAmount *hexutil.Big `json:"assetManagerBondAmount"`

ColosseumCreationPeriodSeconds uint64 `json:"colosseumCreationPeriodSeconds"`
ColosseumBisectionTimeout uint64 `json:"colosseumBisectionTimeout"`
Expand Down Expand Up @@ -408,6 +442,9 @@ func (d *DeployConfig) Check() error {
}
[Kroma: END] */
// [Kroma: START]
if d.GovernanceTokenProxySalt == (common.Hash{}) {
return fmt.Errorf("%w: GovernanceTokenProxySalt cannot be empty hash", ErrInvalidDeployConfig)
}
if d.MintManagerOwner == (common.Address{}) {
return fmt.Errorf("%w: MintManagerOwner cannot be address(0)", ErrInvalidDeployConfig)
}
Expand Down Expand Up @@ -500,6 +537,54 @@ func (d *DeployConfig) Check() error {
if d.ValidatorPoolRoundDuration == 0 {
return fmt.Errorf("%w: ValidatorPoolRoundDuration cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerTrustedValidator == (common.Address{}) {
return fmt.Errorf("%w: ValidatorManagerTrustedValidator cannot be address(0)", ErrInvalidDeployConfig)
}
if d.ValidatorManagerMinRegisterAmount == nil {
return fmt.Errorf("%w: ValidatorManagerMinRegisterAmount cannot be nil", ErrInvalidDeployConfig)
}
if d.ValidatorManagerMinActivateAmount == nil {
return fmt.Errorf("%w: ValidatorManagerMinActivateAmount cannot be nil", ErrInvalidDeployConfig)
}
if d.ValidatorManagerMinActivateAmount.ToInt().Cmp(d.ValidatorManagerMinRegisterAmount.ToInt()) < 0 {
return fmt.Errorf("%w: ValidatorManagerMinActivateAmount must equal or more than ValidatorManagerMinRegisterAmount", ErrInvalidDeployConfig)
}
if d.ValidatorManagerCommissionChangeDelaySeconds == 0 {
return fmt.Errorf("%w: ValidatorManagerCommissionChangeDelaySeconds cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerRoundDurationSeconds == 0 {
return fmt.Errorf("%w: ValidatorManagerRoundDurationSeconds cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerSoftJailPeriodSeconds == 0 {
return fmt.Errorf("%w: ValidatorManagerSoftJailPeriodSeconds cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerHardJailPeriodSeconds == 0 {
return fmt.Errorf("%w: ValidatorManagerHardJailPeriodSeconds cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerJailThreshold == 0 {
return fmt.Errorf("%w: ValidatorManagerJailThreshold cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerMaxFinalizations == 0 {
return fmt.Errorf("%w: ValidatorManagerMaxFinalizations cannot be 0", ErrInvalidDeployConfig)
}
if d.ValidatorManagerBaseReward == nil {
return fmt.Errorf("%w: ValidatorManagerBaseReward cannot be nil", ErrInvalidDeployConfig)
}
if d.AssetManagerKgh == (common.Address{}) {
return fmt.Errorf("%w: AssetManagerKgh cannot be address(0)", ErrInvalidDeployConfig)
}
if d.AssetManagerVault == (common.Address{}) {
return fmt.Errorf("%w: AssetManagerVault cannot be address(0)", ErrInvalidDeployConfig)
}
if d.AssetManagerMinDelegationPeriod == 0 {
return fmt.Errorf("%w: AssetManagerMinDelegationPeriod cannot be 0", ErrInvalidDeployConfig)
}
if d.AssetManagerBondAmount == nil {
return fmt.Errorf("%w: AssetManagerBondAmount cannot be nil", ErrInvalidDeployConfig)
}
if d.L2OutputOracleSubmissionInterval*d.L2BlockTime != d.ValidatorManagerRoundDurationSeconds*2 {
return fmt.Errorf("%w: double of ValidatorManagerRoundDurationSeconds must equal to L2OutputOracleSubmissionInterval", ErrInvalidDeployConfig)
}
if d.L2OutputOracleSubmissionInterval*d.L2BlockTime != d.ValidatorPoolRoundDuration*2 {
return fmt.Errorf("%w: double of ValidatorPoolRoundDuration must equal to L2OutputOracleSubmissionInterval", ErrInvalidDeployConfig)
}
Expand Down Expand Up @@ -759,7 +844,9 @@ type L1Deployments struct {
// [Kroma: START]
Colosseum common.Address `json:"Colosseum"`
ColosseumProxy common.Address `json:"ColosseumProxy"`
L1GovernanceToken common.Address `json:"L1GovernanceToken"`
L1GovernanceTokenProxy common.Address `json:"L1GovernanceTokenProxy"`
L1MintManager common.Address `json:"L1MintManager"`
Poseidon2 common.Address `json:"Poseidon2"`
SecurityCouncil common.Address `json:"SecurityCouncil"`
SecurityCouncilProxy common.Address `json:"SecurityCouncilProxy"`
Expand All @@ -771,6 +858,10 @@ type L1Deployments struct {
UpgradeGovernorProxy common.Address `json:"UpgradeGovernorProxy"`
ValidatorPool common.Address `json:"ValidatorPool"`
ValidatorPoolProxy common.Address `json:"ValidatorPoolProxy"`
AssetManager common.Address `json:"AssetManager"`
AssetManagerProxy common.Address `json:"AssetManagerProxy"`
ValidatorManager common.Address `json:"ValidatorManager"`
ValidatorManagerProxy common.Address `json:"ValidatorManagerProxy"`
ZKMerkleTrie common.Address `json:"ZKMerkleTrie"`
ZKVerifier common.Address `json:"ZKVerifier"`
ZKVerifierProxy common.Address `json:"ZKVerifierProxy"`
Expand Down Expand Up @@ -810,12 +901,6 @@ func (d *L1Deployments) Check(deployConfig *DeployConfig) error {
name == "DataAvailabilityChallengeProxy") {
continue
}
// [Kroma: START]
// Skip contract that will be deployed later in setup
if name == "L1GovernanceTokenProxy" {
continue
}
// [Kroma: END]
if val.Field(i).Interface().(common.Address) == (common.Address{}) {
return fmt.Errorf("%s is not set", name)
}
Expand Down
5 changes: 4 additions & 1 deletion kroma-chain-ops/genesis/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"

"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -115,6 +114,10 @@ func TestL1Deployments(t *testing.T) {
require.NotEqual(t, deployments.UpgradeGovernorProxy, common.Address{})
require.NotEqual(t, deployments.ValidatorPool, common.Address{})
require.NotEqual(t, deployments.ValidatorPoolProxy, common.Address{})
require.NotEqual(t, deployments.AssetManager, common.Address{})
require.NotEqual(t, deployments.AssetManagerProxy, common.Address{})
require.NotEqual(t, deployments.ValidatorManager, common.Address{})
require.NotEqual(t, deployments.ValidatorManagerProxy, common.Address{})
require.NotEqual(t, deployments.ZKMerkleTrie, common.Address{})
require.NotEqual(t, deployments.ZKVerifier, common.Address{})
require.NotEqual(t, deployments.ZKVerifierProxy, common.Address{})
Expand Down
30 changes: 28 additions & 2 deletions kroma-chain-ops/genesis/layer_one.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
Expand All @@ -13,7 +14,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"

"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/kroma-network/kroma/kroma-bindings/bindings"
"github.com/kroma-network/kroma/kroma-bindings/predeploys"
)
Expand Down Expand Up @@ -101,6 +101,8 @@ func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployme
return memDB.Genesis(), nil
}

// [Kroma: START]

// PostProcessL1DeveloperGenesis will apply post processing to the L1 genesis
// state. This is required to handle edge cases in the genesis generation.
// `block.number` is used during deployment and without specifically setting
Expand All @@ -119,7 +121,6 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1
return fmt.Errorf("portal proxy doesn't exist at %s", deployments.KromaPortalProxy)
}

// [Kroma: START]
slot, err := getStorageSlot("KromaPortal", "params")
if err != nil {
return err
Expand Down Expand Up @@ -192,6 +193,31 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1
//setup beacon deposit contract
log.Info("Set BeaconDepositContractCode")
stateDB.SetCode(predeploys.BeaconDepositContractAddr, predeploys.BeaconDepositContractCode)

//setup governance token balances on L1
log.Info("Set GovernanceToken balance on L1")
if !stateDB.Exist(deployments.L1GovernanceTokenProxy) {
return fmt.Errorf("l1GovernanceToken proxy doesn't exist at %s", deployments.L1GovernanceTokenProxy)
}

slot, err = getStorageSlot("GovernanceToken", "_balances")
if err != nil {
return err
}

bigVal, success := new(big.Int).SetString("1000000000000000000000000", 10)
if !success {
return fmt.Errorf("failed to set governance token balance")
}
val = common.BigToHash(bigVal)
for _, account := range DevAccounts {
addrToBytes := append(make([]byte, 12), account.Bytes()...)
addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()...))
stateDB.SetState(deployments.L1GovernanceTokenProxy, addrSlot, val)

log.Info("Post process update", "name", "GovernanceToken", "address", deployments.L1GovernanceTokenProxy, "slot", addrSlot.Hex(), "afterVal", val.Hex())
}

return nil
}

Expand Down
12 changes: 8 additions & 4 deletions kroma-chain-ops/genesis/layer_one_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ import (
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"

"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"

"github.com/kroma-network/kroma/kroma-bindings/bindings"
"github.com/kroma-network/kroma/kroma-bindings/predeploys"
"github.com/stretchr/testify/require"
)

// TestBuildL1DeveloperGenesis tests that the L1 genesis block can be built
Expand Down Expand Up @@ -61,6 +61,10 @@ func TestBuildL1DeveloperGenesis(t *testing.T) {
require.NoError(t, err)
require.Equal(t, deployments.ValidatorPoolProxy, valPoolAddr)

valMgrAddr, err := oracle.VALIDATORMANAGER(callOpts)
require.NoError(t, err)
require.Equal(t, deployments.ValidatorManagerProxy, valMgrAddr)

colosseumAddr, err := oracle.COLOSSEUM(callOpts)
require.NoError(t, err)
require.Equal(t, deployments.ColosseumProxy, colosseumAddr)
Expand Down
365 changes: 219 additions & 146 deletions kroma-chain-ops/genesis/testdata/allocs-l1.json

Large diffs are not rendered by default.

39 changes: 23 additions & 16 deletions kroma-chain-ops/genesis/testdata/deploy.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
{
"Colosseum": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"AssetManager": "0x82e01223d51Eb87e16A03E24687EDF0F294da6f1",
"AssetManagerProxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"Colosseum": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"ColosseumProxy": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
"KromaMintableERC20Factory": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"KromaMintableERC20Factory": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"KromaMintableERC20FactoryProxy": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
"KromaPortal": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"KromaPortal": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"KromaPortalProxy": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
"L1CrossDomainMessenger": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"L1CrossDomainMessenger": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"L1CrossDomainMessengerProxy": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"L1ERC721Bridge": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"L1ERC721Bridge": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"L1ERC721BridgeProxy": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"L1StandardBridge": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"L1GovernanceToken": "0x5f3f1dBD7B74C6B46e8c44f98792A1dAf8d69154",
"L1GovernanceTokenProxy": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
"L1MintManager": "0x1291Be112d480055DaFd8a610b7d1e203891C274",
"L1StandardBridge": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"L1StandardBridgeProxy": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"L2OutputOracle": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"L2OutputOracle": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
"L2OutputOracleProxy": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
"Poseidon2": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"Poseidon2": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"ProxyAdmin": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"SecurityCouncil": "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00",
"SecurityCouncil": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570",
"SecurityCouncilProxy": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"SecurityCouncilToken": "0xf5059a5D33d5853360D16C683c16e67980206f36",
"SecurityCouncilToken": "0x998abeb3E57409262aE5b751f60747921B33613E",
"SecurityCouncilTokenProxy": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"SystemConfig": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"SystemConfig": "0xf5059a5D33d5853360D16C683c16e67980206f36",
"SystemConfigProxy": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"TimeLock": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
"TimeLock": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF",
"TimeLockProxy": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"UpgradeGovernor": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf",
"UpgradeGovernor": "0x9d4454B023096f34B160D6B654540c56A1F81688",
"UpgradeGovernorProxy": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"ValidatorPool": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"ValidatorManager": "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0",
"ValidatorManagerProxy": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ValidatorPool": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"ValidatorPoolProxy": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"ZKMerkleTrie": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ZKVerifier": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
"ZKMerkleTrie": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
"ZKVerifier": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"ZKVerifierProxy": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"
}
Loading

0 comments on commit 87fc8ab

Please sign in to comment.