Skip to content

Commit

Permalink
feat(chain-ops): make MintManager and GovernanceToken predeployed
Browse files Browse the repository at this point in the history
  • Loading branch information
Pangssu committed Mar 25, 2024
1 parent bbf998e commit 74f4eab
Show file tree
Hide file tree
Showing 11 changed files with 463 additions and 213 deletions.
25 changes: 25 additions & 0 deletions kroma-chain-ops/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# kroma-chain-ops

This package contains utilities for working with chain state.

## check-l2

The `check-l2` binary is used for verifying that an OP Stack L2
has been configured correctly. It iterates over all 256 predeployed
proxies to make sure they are configured correctly with the correct
proxy admin address. After that, it checks that all [predeploys](../kroma-bindings/predeploys/addresses.go)
are configured and aliased correctly. Additional contract-specific
checks ensure configuration like ownership, version, and storage
is set correctly for the predeploys.

#### Usage

It can be built and run using the [Makefile](./Makefile) `check-l2` target.
Run `make check-l2` to create a binary in [./bin/check-l2](./bin/check-l2)
that can be executed by providing the `--l1-rpc-url` and `--l2-rpc-url` flags.

```sh
./bin/check-l2 \
--l2-rpc-url http://localhost:9545 \
--l1-rpc-url http://localhost:8545
```
115 changes: 106 additions & 9 deletions kroma-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"reflect"
"strings"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
gstate "github.com/ethereum/go-ethereum/core/state"
Expand All @@ -19,11 +20,11 @@ import (
"github.com/ethereum/go-ethereum/rpc"

"github.com/ethereum-optimism/optimism/op-bindings/hardhat"
"github.com/kroma-network/kroma/kroma-bindings/predeploys"
"github.com/kroma-network/kroma/kroma-chain-ops/immutables"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/kroma-network/kroma/kroma-bindings/predeploys"
"github.com/kroma-network/kroma/kroma-chain-ops/immutables"
)

var (
Expand Down Expand Up @@ -253,6 +254,21 @@ type DeployConfig struct {
ZKVerifierHashScalar *hexutil.Big `json:"zkVerifierHashScalar"`
ZKVerifierM56Px *hexutil.Big `json:"zkVerifierM56Px"`
ZKVerifierM56Py *hexutil.Big `json:"zkVerifierM56Py"`

// L1GovernanceTokenProxy represents the address of the L1GovernanceTokenProxy on L1.
L1GovernanceTokenProxy common.Address `json:"l1GovernanceTokenProxy"`
// MintManagerMintActivatedBlock is the number of the L2 block where the mint function is activated.
MintManagerMintActivatedBlock *hexutil.Big `json:"mintManagerMintActivatedBlock,omitempty"`
// MintManagerInitMintPerBlock is the initial amount of governance tokens minted per block.
MintManagerInitMintPerBlock *hexutil.Big `json:"mintManagerInitMintPerBlock,omitempty"`
// MintManagerSlidingWindowBlocks is the period (in blocks) which the mint amount per block decreases.
MintManagerSlidingWindowBlocks uint64 `json:"mintManagerSlidingWindowBlocks"`
// MintManagerDecayingFactor is the ratio by which the mint amount decreases from the previous epoch.
MintManagerDecayingFactor uint64 `json:"mintManagerDecayingFactor"`
// MintManagerRecipients is an array of recipient addresses to which minted tokens will be distributed.
MintManagerRecipients []common.Address `json:"mintManagerRecipients"`
// MintManagerShares is an array of each recipient's shares of minted tokens.
MintManagerShares []uint64 `json:"mintManagerShares"`
// [Kroma: END]
}

Expand Down Expand Up @@ -354,8 +370,22 @@ func (d *DeployConfig) Check() error {
if d.GovernanceTokenSymbol == "" {
return fmt.Errorf("%w: GovernanceToken.symbol cannot be empty", ErrInvalidDeployConfig)
}
if d.GovernanceTokenOwner == (common.Address{}) {
return fmt.Errorf("%w: GovernanceToken owner cannot be address(0)", ErrInvalidDeployConfig)
// [Kroma: START]
// if d.GovernanceTokenOwner == (common.Address{}) {
// return fmt.Errorf("%w: GovernanceToken owner cannot be address(0)", ErrInvalidDeployConfig)
// }
// [Kroma: END]
if d.MintManagerSlidingWindowBlocks == 0 {
return fmt.Errorf("%w: MintManagerSlidingWindowBlocks cannot be 0", ErrInvalidDeployConfig)
}
if d.MintManagerDecayingFactor == 0 {
return fmt.Errorf("%w: MintManagerDecayingFactor cannot be 0", ErrInvalidDeployConfig)
}
if len(d.MintManagerRecipients) == 0 {
return fmt.Errorf("%w: MintManagerRecipients array cannot be empty", ErrInvalidDeployConfig)
}
if len(d.MintManagerRecipients) != len(d.MintManagerShares) {
return fmt.Errorf("%w: MintManagerRecipients and MintManagerShares must be the same length", ErrInvalidDeployConfig)
}
}
// L2 block time must always be smaller than L1 block time
Expand Down Expand Up @@ -451,6 +481,12 @@ func (d *DeployConfig) CheckAddresses() error {
if d.KromaPortalProxy == (common.Address{}) {
return fmt.Errorf("%w: KromaPortalProxy cannot be address(0)", ErrInvalidDeployConfig)
}

// [Kroma: START]
if d.L1GovernanceTokenProxy == (common.Address{}) {
return fmt.Errorf("%w: L1GovernanceTokenProxy cannot be address(0)", ErrInvalidDeployConfig)
}
// [Kroma: END]
return nil
}

Expand All @@ -464,6 +500,7 @@ func (d *DeployConfig) SetDeployments(deployments *L1Deployments) {

// [Kroma: START]
d.ValidatorPoolProxy = deployments.ValidatorPoolProxy
d.L1GovernanceTokenProxy = deployments.L1GovernanceTokenProxy
// [Kroma: END]
}

Expand Down Expand Up @@ -510,6 +547,7 @@ func (d *DeployConfig) GetDeployedAddresses(hh *hardhat.Hardhat) error {
d.KromaPortalProxy = kromaPortalProxyDeployment.Address
}

// [Kroma: START]
if d.ValidatorPoolProxy == (common.Address{}) {
validatorPoolProxyDeployment, err := hh.GetDeployment("ValidatorPoolProxy")
if err != nil {
Expand All @@ -518,6 +556,15 @@ func (d *DeployConfig) GetDeployedAddresses(hh *hardhat.Hardhat) error {
d.ValidatorPoolProxy = validatorPoolProxyDeployment.Address
}

if d.L1GovernanceTokenProxy == (common.Address{}) {
L1GovernanceTokenProxyDeployment, err := hh.GetDeployment("L1GovernanceTokenProxy")
if err != nil {
return fmt.Errorf("cannot find L1GovernanceTokenProxy artifact: %w", err)
}
d.L1GovernanceTokenProxy = L1GovernanceTokenProxyDeployment.Address
}
// [Kroma: END]

return nil
}

Expand Down Expand Up @@ -694,6 +741,8 @@ 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"`
Poseidon2 common.Address `json:"Poseidon2"`
SecurityCouncil common.Address `json:"SecurityCouncil"`
SecurityCouncilProxy common.Address `json:"SecurityCouncilProxy"`
Expand Down Expand Up @@ -820,6 +869,21 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables

rewardDivider := config.FinalizationPeriodSeconds / (config.L2OutputOracleSubmissionInterval * config.L2BlockTime)

// Set the default value for the initial mint amount per block.
initMintPerBlock := big.NewInt(1e18)
if config.MintManagerInitMintPerBlock != nil {
v := new(big.Int).Set(config.MintManagerInitMintPerBlock.ToInt())
if v.Uint64() > 0 {
initMintPerBlock = v
}
}

// Set the default value for the block where the mint function is activated.
mintActivatedBlock := abi.MaxUint256
if config.MintManagerMintActivatedBlock != nil {
mintActivatedBlock = new(big.Int).Set(config.MintManagerMintActivatedBlock.ToInt())
}

cfg := immutables.PredeploysImmutableConfig{
L2ToL1MessagePasser: struct{}{},
// [Kroma: START]
Expand All @@ -840,11 +904,19 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables
// Messenger: predeploys.L2CrossDomainMessengerAddr,
// [Kroma: END]
},
L1BlockNumber: struct{}{},
GasPriceOracle: struct{}{},
L1Block: struct{}{},
GovernanceToken: struct{}{},
L1BlockNumber: struct{}{},
GasPriceOracle: struct{}{},
L1Block: struct{}{},
// [Kroma: START]
GovernanceToken: struct {
Bridge common.Address
RemoteToken common.Address
MintManager common.Address
}{
Bridge: predeploys.L2StandardBridgeAddr,
RemoteToken: config.L1GovernanceTokenProxy,
MintManager: predeploys.MintManagerAddr,
},
// LegacyMessagePasser: struct{}{},
// [Kroma: END]
L2ERC721Bridge: struct {
Expand Down Expand Up @@ -895,6 +967,17 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables
ValidatorPoolAddress: config.ValidatorPoolProxy,
RewardDivider: new(big.Int).SetUint64(rewardDivider),
},
MintManager: struct {
MintActivatedBlock *big.Int
InitMintPerBlock *big.Int
SlidingWindowBlocks *big.Int
DecayingFactor *big.Int
}{
MintActivatedBlock: mintActivatedBlock,
InitMintPerBlock: initMintPerBlock,
SlidingWindowBlocks: new(big.Int).SetUint64(config.MintManagerSlidingWindowBlocks),
DecayingFactor: new(big.Int).SetUint64(config.MintManagerDecayingFactor),
},
// [Kroma: END]
}

Expand Down Expand Up @@ -961,8 +1044,22 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
storage["GovernanceToken"] = state.StorageValues{
"_name": config.GovernanceTokenName,
"_symbol": config.GovernanceTokenSymbol,
"_owner": config.GovernanceTokenOwner,
// "_owner": config.GovernanceTokenOwner,
}

// [Kroma: START]
shares := make(map[any]any)
for i, recipient := range config.MintManagerRecipients {
shares[recipient] = config.MintManagerShares[i]
}

storage["MintManager"] = state.StorageValues{
"_initialized": 1,
"_initializing": false,
"recipients": config.MintManagerRecipients,
"shareOf": shares,
}
// [Kroma: END]
}
storage["ProxyAdmin"] = state.StorageValues{
"_owner": config.ProxyAdminOwner,
Expand Down
6 changes: 3 additions & 3 deletions kroma-chain-ops/genesis/layer_two_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"

"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/kroma-network/kroma/kroma-bindings/bindings"
"github.com/kroma-network/kroma/kroma-bindings/predeploys"
"github.com/kroma-network/kroma/kroma-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-service/eth"
)

var writeFile bool
Expand Down Expand Up @@ -79,7 +79,7 @@ func testBuildL2Genesis(t *testing.T, config *genesis.DeployConfig) *core.Genesi

if writeFile {
file, _ := json.MarshalIndent(gen, "", " ")
_ = os.WriteFile("genesis.json", file, 0644)
_ = os.WriteFile("genesis.json", file, 0o644)
}
return gen
}
Expand All @@ -90,7 +90,7 @@ func TestBuildL2MainnetGenesis(t *testing.T) {
config.EnableGovernance = true
config.FundDevAccounts = false
gen := testBuildL2Genesis(t, config)
require.Equal(t, 526, len(gen.Alloc))
require.Equal(t, 528, len(gen.Alloc))
}

func TestBuildL2MainnetNoGovernanceGenesis(t *testing.T) {
Expand Down
351 changes: 191 additions & 160 deletions kroma-chain-ops/genesis/testdata/allocs-l1.json

Large diffs are not rendered by default.

34 changes: 18 additions & 16 deletions kroma-chain-ops/genesis/testdata/deploy.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
{
"Colosseum": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"Colosseum": "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
"ColosseumProxy": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
"KromaMintableERC20Factory": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"KromaMintableERC20Factory": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
"KromaMintableERC20FactoryProxy": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
"KromaPortal": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"KromaPortal": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
"KromaPortalProxy": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
"L1CrossDomainMessenger": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"L1CrossDomainMessenger": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
"L1CrossDomainMessengerProxy": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"L1ERC721Bridge": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"L1ERC721Bridge": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
"L1ERC721BridgeProxy": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"L1StandardBridge": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"L1GovernanceToken": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
"L1GovernanceTokenProxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"L1StandardBridge": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d",
"L1StandardBridgeProxy": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"L2OutputOracle": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"L2OutputOracle": "0xc5a5C42992dECbae36851359345FE25997F5C42d",
"L2OutputOracleProxy": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
"Poseidon2": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"Poseidon2": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ProxyAdmin": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"SecurityCouncil": "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00",
"SecurityCouncil": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570",
"SecurityCouncilProxy": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"SecurityCouncilToken": "0xf5059a5D33d5853360D16C683c16e67980206f36",
"SecurityCouncilToken": "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
"SecurityCouncilTokenProxy": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"SystemConfig": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"SystemConfig": "0x851356ae760d987E095750cCeb3bC6014560891C",
"SystemConfigProxy": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"TimeLock": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
"TimeLock": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF",
"TimeLockProxy": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"UpgradeGovernor": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf",
"UpgradeGovernor": "0x9d4454B023096f34B160D6B654540c56A1F81688",
"UpgradeGovernorProxy": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"ValidatorPool": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"ValidatorPool": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
"ValidatorPoolProxy": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"ZKMerkleTrie": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ZKVerifier": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
"ZKMerkleTrie": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"ZKVerifier": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
"ZKVerifierProxy": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"
}
34 changes: 18 additions & 16 deletions kroma-chain-ops/genesis/testdata/l1-deployments.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
{
"Colosseum": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"Colosseum": "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
"ColosseumProxy": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
"KromaMintableERC20Factory": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"KromaMintableERC20Factory": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
"KromaMintableERC20FactoryProxy": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
"KromaPortal": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"KromaPortal": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
"KromaPortalProxy": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
"L1CrossDomainMessenger": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"L1CrossDomainMessenger": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
"L1CrossDomainMessengerProxy": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"L1ERC721Bridge": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"L1ERC721Bridge": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
"L1ERC721BridgeProxy": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"L1StandardBridge": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"L1GovernanceToken": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
"L1GovernanceTokenProxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"L1StandardBridge": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d",
"L1StandardBridgeProxy": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"L2OutputOracle": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"L2OutputOracle": "0xc5a5C42992dECbae36851359345FE25997F5C42d",
"L2OutputOracleProxy": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
"Poseidon2": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"Poseidon2": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ProxyAdmin": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"SecurityCouncil": "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00",
"SecurityCouncil": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570",
"SecurityCouncilProxy": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"SecurityCouncilToken": "0xf5059a5D33d5853360D16C683c16e67980206f36",
"SecurityCouncilToken": "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
"SecurityCouncilTokenProxy": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"SystemConfig": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"SystemConfig": "0x851356ae760d987E095750cCeb3bC6014560891C",
"SystemConfigProxy": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"TimeLock": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
"TimeLock": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF",
"TimeLockProxy": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"UpgradeGovernor": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf",
"UpgradeGovernor": "0x9d4454B023096f34B160D6B654540c56A1F81688",
"UpgradeGovernorProxy": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"ValidatorPool": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"ValidatorPool": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
"ValidatorPoolProxy": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"ZKMerkleTrie": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"ZKVerifier": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
"ZKMerkleTrie": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"ZKVerifier": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
"ZKVerifierProxy": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,19 @@
"colosseumSegmentsLengths": "2,2,3,3",
"zkVerifierHashScalar": "0x1545b1bf82c58ee35648bd877da9c5010193e82b036b16bf382acf31bc2ab576",
"zkVerifierM56Px": "0x15ae1a8e3b993dd9aadc8f9086d1ea239d4cd5c09cfa445f337e1b60d7b3eb87",
"zkVerifierM56Py": "0x2c702ede24f9db8c8c9a439975facd3872a888c5f84f58b3b5f5a5623bac945a"
"zkVerifierM56Py": "0x2c702ede24f9db8c8c9a439975facd3872a888c5f84f58b3b5f5a5623bac945a",
"mintManagerMintActivatedBlock": "0x0",
"mintManagerInitMintPerBlock": "0xde0b6b3a7640000",
"mintManagerSlidingWindowBlocks": 3888000,
"mintManagerDecayingFactor": 92224,
"mintManagerRecipients": [
"0x4200000000000000000000000000000000000006",
"0x4200000000000000000000000000000000000007",
"0x4200000000000000000000000000000000000008"
],
"mintManagerShares": [
20000,
30000,
50000
]
}
Loading

0 comments on commit 74f4eab

Please sign in to comment.