Add governor and staking configs for each network
This commit is contained in:
@@ -15,6 +15,9 @@ import { logUtils, providerUtils } from '@0x/utils';
|
|||||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
import { SupportedProvider } from 'ethereum-types';
|
import { SupportedProvider } from 'ethereum-types';
|
||||||
|
|
||||||
|
import { getConfigsByChainId } from './utils/configs_by_chain';
|
||||||
|
import { getTimelockRegistrationsAsync } from './utils/timelocks';
|
||||||
|
|
||||||
// NOTE: add your own Infura Project ID to RPC urls before running
|
// NOTE: add your own Infura Project ID to RPC urls before running
|
||||||
const INFURA_PROJECT_ID = '';
|
const INFURA_PROJECT_ID = '';
|
||||||
|
|
||||||
@@ -30,6 +33,7 @@ async function testContractConfigsAsync(provider: SupportedProvider): Promise<vo
|
|||||||
const web3Wrapper = new Web3Wrapper(provider);
|
const web3Wrapper = new Web3Wrapper(provider);
|
||||||
const chainId = await web3Wrapper.getChainIdAsync();
|
const chainId = await web3Wrapper.getChainIdAsync();
|
||||||
const addresses = getContractAddressesForChainOrThrow(chainId);
|
const addresses = getContractAddressesForChainOrThrow(chainId);
|
||||||
|
const configs = getConfigsByChainId(chainId);
|
||||||
|
|
||||||
function warnIfMismatch(actual: any, expected: any, message: string): void {
|
function warnIfMismatch(actual: any, expected: any, message: string): void {
|
||||||
if (actual !== expected) {
|
if (actual !== expected) {
|
||||||
@@ -246,10 +250,10 @@ async function testContractConfigsAsync(provider: SupportedProvider): Promise<vo
|
|||||||
warnIfMismatch(stakingLogicAddress, addresses.staking, 'Unexpected Staking contract attached to StakingProxy');
|
warnIfMismatch(stakingLogicAddress, addresses.staking, 'Unexpected Staking contract attached to StakingProxy');
|
||||||
|
|
||||||
const zrxVaultAddress = await stakingContract.getZrxVault.callAsync();
|
const zrxVaultAddress = await stakingContract.getZrxVault.callAsync();
|
||||||
warnIfMismatch(zrxVaultAddress, addresses.zrxVault, 'Unexpected ZrxVault set in Staking contract');
|
warnIfMismatch(zrxVaultAddress, addresses.zrxVault, 'Unexpected ZrxVault set in StakingProxy');
|
||||||
|
|
||||||
const wethAddress = await stakingContract.getWethContract.callAsync();
|
const wethAddress = await stakingContract.getWethContract.callAsync();
|
||||||
warnIfMismatch(wethAddress, addresses.etherToken, 'Unexpected WETH contract set in Staking contract');
|
warnIfMismatch(wethAddress, addresses.etherToken, 'Unexpected WETH contract set in StakingProxy');
|
||||||
|
|
||||||
const stakingProxyOwner = await stakingProxy.owner.callAsync();
|
const stakingProxyOwner = await stakingProxy.owner.callAsync();
|
||||||
warnIfMismatch(stakingProxyOwner, addresses.zeroExGovernor, 'Unexpected StakingProxy owner');
|
warnIfMismatch(stakingProxyOwner, addresses.zeroExGovernor, 'Unexpected StakingProxy owner');
|
||||||
@@ -270,15 +274,92 @@ async function testContractConfigsAsync(provider: SupportedProvider): Promise<vo
|
|||||||
warnIfMismatch(zrxVaultAuthorizedAddresses.length, 1, 'Unexpected number of authorized addresses in ZrxVault');
|
warnIfMismatch(zrxVaultAuthorizedAddresses.length, 1, 'Unexpected number of authorized addresses in ZrxVault');
|
||||||
const isGovernorAuthorizedInZrxVault = await zrxVault.authorized.callAsync(addresses.zeroExGovernor);
|
const isGovernorAuthorizedInZrxVault = await zrxVault.authorized.callAsync(addresses.zeroExGovernor);
|
||||||
warnIfMismatch(isGovernorAuthorizedInZrxVault, true, 'ZeroExGovernor not authorized in ZrxVault');
|
warnIfMismatch(isGovernorAuthorizedInZrxVault, true, 'ZeroExGovernor not authorized in ZrxVault');
|
||||||
|
|
||||||
|
const params = await stakingContract.getParams.callAsync();
|
||||||
|
warnIfMismatch(
|
||||||
|
params[0].toNumber(),
|
||||||
|
configs.staking.epochDurationInSeconds.toNumber(),
|
||||||
|
'Unexpected epoch duration in StakingProxy',
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
params[1].toString(),
|
||||||
|
configs.staking.rewardDelegatedStakeWeight.toString(),
|
||||||
|
'Unexpected delegated stake weight in StakingProxy',
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
params[2].toNumber(),
|
||||||
|
configs.staking.minimumPoolStake.toNumber(),
|
||||||
|
'Unexpected minimum pool stake in StakingProxy',
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
params[3].toString(),
|
||||||
|
configs.staking.cobbDouglasAlphaNumerator.toString(),
|
||||||
|
'Unexpected alpha numerator in StakingProxy',
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
params[4].toString(),
|
||||||
|
configs.staking.cobbDouglasAlphaDenominator.toString(),
|
||||||
|
'Unexpected alpha denominator in StakingProxy',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement ZeroExGovernor config tests
|
async function verifyZeroExGovernorConfigsAsync(): Promise<void> {
|
||||||
// async function verifyAssetProxyOwnerConfigsAsync(): Promise<void> {}
|
const timelockRegistrations = await getTimelockRegistrationsAsync(provider);
|
||||||
|
for (const timelockRegistration of timelockRegistrations) {
|
||||||
|
const actualRegistration = await governor.functionCallTimeLocks.callAsync(
|
||||||
|
timelockRegistration.functionSelector,
|
||||||
|
timelockRegistration.destination,
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
actualRegistration[0],
|
||||||
|
true,
|
||||||
|
`Function ${timelockRegistration.functionSelector} at address ${
|
||||||
|
timelockRegistration.destination
|
||||||
|
} not registered in ZeroExGovernor`,
|
||||||
|
);
|
||||||
|
warnIfMismatch(
|
||||||
|
actualRegistration[1].toNumber(),
|
||||||
|
timelockRegistration.secondsTimeLocked.toNumber(),
|
||||||
|
`Timelock for function ${timelockRegistration.functionSelector} at address ${
|
||||||
|
timelockRegistration.destination
|
||||||
|
} in ZeroExGovernor`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const owners = await governor.getOwners.callAsync();
|
||||||
|
warnIfMismatch(
|
||||||
|
owners.length,
|
||||||
|
configs.zeroExGovernor.owners.length,
|
||||||
|
'Unexpected number of owners in ZeroExGovernor',
|
||||||
|
);
|
||||||
|
owners.forEach((owner, i) => {
|
||||||
|
warnIfMismatch(
|
||||||
|
owners[i],
|
||||||
|
configs.zeroExGovernor.owners[i],
|
||||||
|
`Unexpected owner in ZeroExGovernor at index ${i}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const secondsTimeLocked = await governor.secondsTimeLocked.callAsync();
|
||||||
|
warnIfMismatch(
|
||||||
|
secondsTimeLocked.toNumber(),
|
||||||
|
configs.zeroExGovernor.secondsTimeLocked.toNumber(),
|
||||||
|
'Unexpected secondsTimeLocked in ZeroExGovernor',
|
||||||
|
);
|
||||||
|
|
||||||
|
const confirmationsRequired = await governor.required.callAsync();
|
||||||
|
warnIfMismatch(
|
||||||
|
confirmationsRequired.toNumber(),
|
||||||
|
configs.zeroExGovernor.required.toNumber(),
|
||||||
|
'Unexpected number of confirmations required in ZeroExGovernor',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await verifyExchangeV2ConfigsAsync();
|
await verifyExchangeV2ConfigsAsync();
|
||||||
await verifyExchangeV3ConfigsAsync();
|
await verifyExchangeV3ConfigsAsync();
|
||||||
await verifyStakingConfigsAsync();
|
await verifyStakingConfigsAsync();
|
||||||
await verifyAssetProxyConfigsAsync();
|
await verifyAssetProxyConfigsAsync();
|
||||||
|
await verifyZeroExGovernorConfigsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import { IAuthorizableContract, IOwnableContract } from '@0x/contracts-utils';
|
|||||||
import { AbiEncoder, BigNumber, logUtils, providerUtils } from '@0x/utils';
|
import { AbiEncoder, BigNumber, logUtils, providerUtils } from '@0x/utils';
|
||||||
import { LogWithDecodedArgs, SupportedProvider, TxData } from 'ethereum-types';
|
import { LogWithDecodedArgs, SupportedProvider, TxData } from 'ethereum-types';
|
||||||
|
|
||||||
|
import { getConfigsByChainId } from './utils/configs_by_chain';
|
||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { providerFactory } from './utils/provider_factory';
|
import { providerFactory } from './utils/provider_factory';
|
||||||
|
import { getTimelockRegistrationsAsync } from './utils/timelocks';
|
||||||
|
|
||||||
async function submitAndExecuteTransactionAsync(
|
async function submitAndExecuteTransactionAsync(
|
||||||
governor: ZeroExGovernorContract,
|
governor: ZeroExGovernorContract,
|
||||||
@@ -48,6 +50,7 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||||
const chainId = new BigNumber(await providerUtils.getChainIdAsync(provider));
|
const chainId = new BigNumber(await providerUtils.getChainIdAsync(provider));
|
||||||
const deployedAddresses = getContractAddressesForChainOrThrow(chainId.toNumber());
|
const deployedAddresses = getContractAddressesForChainOrThrow(chainId.toNumber());
|
||||||
|
const configs = getConfigsByChainId(chainId.toNumber());
|
||||||
|
|
||||||
// NOTE: This must be deployed before running these migrations, since its address is hard coded in the
|
// NOTE: This must be deployed before running these migrations, since its address is hard coded in the
|
||||||
// staking logic contract.
|
// staking logic contract.
|
||||||
@@ -113,157 +116,7 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
const authorizableInterface = new IAuthorizableContract(constants.NULL_ADDRESS, provider, txDefaults);
|
const authorizableInterface = new IAuthorizableContract(constants.NULL_ADDRESS, provider, txDefaults);
|
||||||
const ownableInterface = new IOwnableContract(constants.NULL_ADDRESS, provider, txDefaults);
|
const ownableInterface = new IOwnableContract(constants.NULL_ADDRESS, provider, txDefaults);
|
||||||
|
|
||||||
const customTimeLocks = [
|
const customTimeLocks = await getTimelockRegistrationsAsync(provider);
|
||||||
// AssetProxy timelocks
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc20Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc20Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc721Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc721Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc1155Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.erc1155Proxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.multiAssetProxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.multiAssetProxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: erc20BridgeProxy.address,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: erc20BridgeProxy.address,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
// ZrxVault timelocks
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: zrxVault.enterCatastrophicFailure.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: zrxVault.setStakingProxy.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: zrxVault.setZrxProxy.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: ownableInterface.transferOwnership.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: authorizableInterface.addAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.zrxVault,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
// StakingProxy timelocks
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: stakingProxy.attachStakingContract.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: stakingProxy.detachStakingContract.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: stakingLogic.setParams.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 10 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: stakingLogic.addExchangeAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: stakingLogic.removeExchangeAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: ownableInterface.transferOwnership.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: authorizableInterface.addAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: deployedAddresses.stakingProxy,
|
|
||||||
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
// Exchange timelocks
|
|
||||||
{
|
|
||||||
destination: exchange.address,
|
|
||||||
functionSelector: exchange.setProtocolFeeMultiplier.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 10 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: exchange.address,
|
|
||||||
functionSelector: exchange.setProtocolFeeCollectorAddress.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT, // 20 days on mainnet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
destination: exchange.address,
|
|
||||||
functionSelector: exchange.detachProtocolFeeCollector.getSelector(),
|
|
||||||
secondsTimeLocked: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const governor = await ZeroExGovernorContract.deployFrom0xArtifactAsync(
|
const governor = await ZeroExGovernorContract.deployFrom0xArtifactAsync(
|
||||||
multisigArtifacts.ZeroExGovernor,
|
multisigArtifacts.ZeroExGovernor,
|
||||||
@@ -273,9 +126,9 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
customTimeLocks.map(timeLockInfo => timeLockInfo.functionSelector),
|
customTimeLocks.map(timeLockInfo => timeLockInfo.functionSelector),
|
||||||
customTimeLocks.map(timeLockInfo => timeLockInfo.destination),
|
customTimeLocks.map(timeLockInfo => timeLockInfo.destination),
|
||||||
customTimeLocks.map(timeLockInfo => timeLockInfo.secondsTimeLocked),
|
customTimeLocks.map(timeLockInfo => timeLockInfo.secondsTimeLocked),
|
||||||
constants.ASSET_PROXY_OWNER_OWNERS,
|
configs.zeroExGovernor.owners,
|
||||||
constants.ASSET_PROXY_OWNER_CONFIRMATIONS,
|
configs.zeroExGovernor.required,
|
||||||
constants.ASSET_PROXY_OWNER_TIMELOCK,
|
configs.zeroExGovernor.secondsTimeLocked,
|
||||||
);
|
);
|
||||||
|
|
||||||
logUtils.log('Configuring Exchange...');
|
logUtils.log('Configuring Exchange...');
|
||||||
@@ -426,7 +279,7 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
const networkId = 4;
|
const networkId = 4;
|
||||||
const rpcUrl = 'https://rinkeby.infura.io/v3/';
|
const rpcUrl = 'https://rinkeby.infura.io/v3/';
|
||||||
const provider = await providerFactory.getLedgerProviderAsync(networkId, rpcUrl);
|
const provider = await providerFactory.getLedgerProviderAsync(networkId, rpcUrl);
|
||||||
await runMigrationsAsync(provider, { from: constants.ASSET_PROXY_OWNER_OWNERS[0], gasPrice: 60000000000 });
|
await runMigrationsAsync(provider, { from: '0x9df8137872ac09a8fee71d0da5c7539923fb9bf0', gasPrice: 60000000000 });
|
||||||
})().catch(err => {
|
})().catch(err => {
|
||||||
logUtils.log(err);
|
logUtils.log(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
55
packages/migrations/src/utils/configs_by_chain.ts
Normal file
55
packages/migrations/src/utils/configs_by_chain.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
import { constants } from './constants';
|
||||||
|
|
||||||
|
export interface ConfigsByChain {
|
||||||
|
zeroExGovernor: { owners: string[]; secondsTimeLocked: BigNumber; required: BigNumber };
|
||||||
|
staking: {
|
||||||
|
epochDurationInSeconds: BigNumber;
|
||||||
|
rewardDelegatedStakeWeight: number;
|
||||||
|
minimumPoolStake: BigNumber;
|
||||||
|
cobbDouglasAlphaNumerator: number;
|
||||||
|
cobbDouglasAlphaDenominator: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable custom-no-magic-numbers
|
||||||
|
export function getConfigsByChainId(chainId: number): ConfigsByChain {
|
||||||
|
const mainnetConfigs = {
|
||||||
|
zeroExGovernor: {
|
||||||
|
owners: [
|
||||||
|
'0x257619b7155d247e43c8b6d90c8c17278ae481f0',
|
||||||
|
'0x5ee2a00f8f01d099451844af7f894f26a57fcbf2',
|
||||||
|
'0x894d623e0e0e8ed12c4a73dada999e275684a37d',
|
||||||
|
],
|
||||||
|
secondsTimeLocked: constants.TWO_WEEKS_IN_SEC,
|
||||||
|
required: new BigNumber(2),
|
||||||
|
},
|
||||||
|
staking: {
|
||||||
|
epochDurationInSeconds: constants.TEN_DAYS_IN_SEC,
|
||||||
|
rewardDelegatedStakeWeight: 10 ** 6 * 0.9,
|
||||||
|
minimumPoolStake: new BigNumber(10).pow(18).times(100),
|
||||||
|
cobbDouglasAlphaNumerator: 2,
|
||||||
|
cobbDouglasAlphaDenominator: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const testnetConfigs = {
|
||||||
|
zeroExGovernor: {
|
||||||
|
owners: [
|
||||||
|
'0x9df8137872ac09a8fee71d0da5c7539923fb9bf0',
|
||||||
|
'0xcf34d44db312d188789f43a63d11cf2bebb4da15',
|
||||||
|
'0x73fd50f2a6beac9cdac9fe87ef68a18edc415831',
|
||||||
|
],
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
required: new BigNumber(1),
|
||||||
|
},
|
||||||
|
staking: {
|
||||||
|
epochDurationInSeconds: constants.TEN_DAYS_IN_SEC.dividedToIntegerBy(2),
|
||||||
|
rewardDelegatedStakeWeight: 10 ** 6 * 0.9,
|
||||||
|
minimumPoolStake: new BigNumber(10).pow(18).times(100),
|
||||||
|
cobbDouglasAlphaNumerator: 2,
|
||||||
|
cobbDouglasAlphaDenominator: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return chainId === constants.MAINNET_CHAIN_ID ? mainnetConfigs : testnetConfigs;
|
||||||
|
}
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
// tslint:disable custom-no-magic-numbers
|
||||||
export const constants = {
|
export const constants = {
|
||||||
ASSET_PROXY_OWNER_OWNERS: [
|
|
||||||
'0x9df8137872ac09a8fee71d0da5c7539923fb9bf0',
|
|
||||||
'0xcf34d44db312d188789f43a63d11cf2bebb4da15',
|
|
||||||
'0x73fd50f2a6beac9cdac9fe87ef68a18edc415831',
|
|
||||||
],
|
|
||||||
ASSET_PROXY_OWNER_TIMELOCK: new BigNumber(0),
|
|
||||||
ASSET_PROXY_OWNER_CONFIRMATIONS: new BigNumber(1),
|
|
||||||
ERC20_PROXY_ID: '0xf47261b0',
|
|
||||||
ERC721_PROXY_ID: '0x02571792',
|
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
KOVAN_RPC_URL: 'https://kovan.infura.io/',
|
|
||||||
KOVAN_CHAIN_ID: 42,
|
|
||||||
MAINNET_RPC_URL: 'https://mainnet.infura.io/',
|
|
||||||
MAINNET_CHAIN_ID: 1,
|
MAINNET_CHAIN_ID: 1,
|
||||||
ZERO_AMOUNT: new BigNumber(0),
|
ZERO_AMOUNT: new BigNumber(0),
|
||||||
|
TWO_WEEKS_IN_SEC: new BigNumber(14)
|
||||||
|
.times(24)
|
||||||
|
.times(60)
|
||||||
|
.times(60),
|
||||||
|
TEN_DAYS_IN_SEC: new BigNumber(10)
|
||||||
|
.times(24)
|
||||||
|
.times(60)
|
||||||
|
.times(60),
|
||||||
|
TWENTY_DAYS_IN_SEC: new BigNumber(20)
|
||||||
|
.times(24)
|
||||||
|
.times(60)
|
||||||
|
.times(60),
|
||||||
};
|
};
|
||||||
|
|||||||
205
packages/migrations/src/utils/timelocks.ts
Normal file
205
packages/migrations/src/utils/timelocks.ts
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||||
|
import { ExchangeContract } from '@0x/contracts-exchange';
|
||||||
|
import { StakingContract, StakingProxyContract, ZrxVaultContract } from '@0x/contracts-staking';
|
||||||
|
import { IAuthorizableContract, IOwnableContract } from '@0x/contracts-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
|
import { SupportedProvider } from 'ethereum-types';
|
||||||
|
|
||||||
|
import { constants } from './constants';
|
||||||
|
|
||||||
|
export interface TimelockRegistration {
|
||||||
|
functionSelector: string;
|
||||||
|
destination: string;
|
||||||
|
secondsTimeLocked: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTimelockRegistrationsAsync(provider: SupportedProvider): Promise<TimelockRegistration[]> {
|
||||||
|
const web3Wrapper = new Web3Wrapper(provider);
|
||||||
|
const chainId = await web3Wrapper.getChainIdAsync();
|
||||||
|
const deployedAddresses = getContractAddressesForChainOrThrow(chainId);
|
||||||
|
|
||||||
|
const authorizableInterface = new IAuthorizableContract(constants.NULL_ADDRESS, provider);
|
||||||
|
const ownableInterface = new IOwnableContract(constants.NULL_ADDRESS, provider);
|
||||||
|
const zrxVault = new ZrxVaultContract(constants.NULL_ADDRESS, provider);
|
||||||
|
const stakingProxy = new StakingProxyContract(constants.NULL_ADDRESS, provider);
|
||||||
|
const exchange = new ExchangeContract(constants.NULL_ADDRESS, provider);
|
||||||
|
const stakingLogic = new StakingContract(constants.NULL_ADDRESS, provider);
|
||||||
|
|
||||||
|
const noTimelockRegistrations = [
|
||||||
|
// AssetProxy timelocks
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc20Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc20Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc721Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc721Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc1155Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc1155Proxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.multiAssetProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.multiAssetProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc20BridgeProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.erc20BridgeProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
// ZrxVault timelocks
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: zrxVault.enterCatastrophicFailure.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
// Exchange timelocks
|
||||||
|
|
||||||
|
{
|
||||||
|
destination: exchange.address,
|
||||||
|
functionSelector: exchange.detachProtocolFeeCollector.getSelector(),
|
||||||
|
secondsTimeLocked: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const customTimelockRegistrations = [
|
||||||
|
// ZrxVault timelocks
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: zrxVault.setStakingProxy.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: zrxVault.setZrxProxy.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: ownableInterface.transferOwnership.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: authorizableInterface.addAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.zrxVault,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
// StakingProxy timelocks
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: stakingProxy.attachStakingContract.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: stakingProxy.detachStakingContract.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: stakingLogic.setParams.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TEN_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: stakingLogic.addExchangeAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: stakingLogic.removeExchangeAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: ownableInterface.transferOwnership.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: authorizableInterface.addAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: deployedAddresses.stakingProxy,
|
||||||
|
functionSelector: authorizableInterface.removeAuthorizedAddressAtIndex.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
// Exchange timelocks
|
||||||
|
{
|
||||||
|
destination: exchange.address,
|
||||||
|
functionSelector: exchange.setProtocolFeeMultiplier.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TEN_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
destination: exchange.address,
|
||||||
|
functionSelector: exchange.setProtocolFeeCollectorAddress.getSelector(),
|
||||||
|
secondsTimeLocked:
|
||||||
|
chainId === constants.MAINNET_CHAIN_ID ? constants.TWENTY_DAYS_IN_SEC : constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return [...noTimelockRegistrations, ...customTimelockRegistrations];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user