Skip to content

Commit

Permalink
Update governance contract & add local deployment script (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
ducthotran2010 authored Nov 10, 2022
1 parent 03fb1bb commit d6ac960
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 98 deletions.
5 changes: 4 additions & 1 deletion contracts/mainchain/MainchainGovernanceAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
import "../extensions/isolated-governance/bridge-operator-governance/BOsGovernanceRelay.sol";
import "../extensions/sequential-governance/GovernanceRelay.sol";
import "../extensions/TransparentUpgradeableProxyV2.sol";
import "../extensions/GovernanceAdmin.sol";
import "../interfaces/IBridge.sol";

Expand Down Expand Up @@ -73,7 +74,9 @@ contract MainchainGovernanceAdmin is AccessControlEnumerable, GovernanceRelay, G
Signature[] calldata _signatures
) external onlyRole(RELAYER_ROLE) {
_relayVotesBySignatures(_operators, _signatures, _period, _getMinimumVoteWeight(), DOMAIN_SEPARATOR);
_bridgeContract.replaceBridgeOperators(_operators);
TransparentUpgradeableProxyV2(payable(bridgeContract())).functionDelegateCall(
abi.encodeWithSelector(_bridgeContract.replaceBridgeOperators.selector, _operators)
);
}

/**
Expand Down
29 changes: 24 additions & 5 deletions contracts/mocks/MockBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,33 @@ pragma solidity ^0.8.9;
import "../interfaces/IBridge.sol";

contract MockBridge is IBridge {
/// @dev Mapping from validator address => last block that the bridge operator is added
mapping(address => uint256) public bridgeOperatorAddedBlock;
/// @dev Bridge operators array
address[] public bridgeOperators;

function replaceBridgeOperators(address[] calldata _list) external override {
while (bridgeOperators.length > 0) {
bridgeOperators.pop();
function replaceBridgeOperators(address[] calldata _list) external {
address _addr;
for (uint256 _i = 0; _i < _list.length; _i++) {
_addr = _list[_i];
if (bridgeOperatorAddedBlock[_addr] == 0) {
bridgeOperators.push(_addr);
}
bridgeOperatorAddedBlock[_addr] = block.number;
}
for (uint _i = 0; _i < _list.length; _i++) {
bridgeOperators.push(_list[_i]);

{
uint256 _i;
while (_i < bridgeOperators.length) {
_addr = bridgeOperators[_i];
if (bridgeOperatorAddedBlock[_addr] < block.number) {
delete bridgeOperatorAddedBlock[_addr];
bridgeOperators[_i] = bridgeOperators[bridgeOperators.length - 1];
bridgeOperators.pop();
continue;
}
_i++;
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ if (!MAINNET_PK) {
console.warn('MAINNET_PK is unset. Using DEFAULT_MNEMONIC');
}

const local: NetworkUserConfig = {
url: 'http://localhost:8545',
accounts: { mnemonic: DEFAULT_MNEMONIC },
};

const devnet: NetworkUserConfig = {
url: DEVNET_URL || 'http://localhost:8545',
accounts: DEVNET_PK ? [DEVNET_PK] : { mnemonic: DEFAULT_MNEMONIC },
Expand Down Expand Up @@ -78,6 +83,7 @@ const config: HardhatUserConfig = {
accountsBalance: '1000000000000000000000000000', // 1B RON
},
},
local,
'ronin-devnet': devnet,
'ronin-testnet': testnet,
'ronin-mainnet': mainnet,
Expand Down
194 changes: 105 additions & 89 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import { ethers } from 'hardhat';
import {
GeneralConfig,
LiteralNetwork,
MainchainGovernanceAdminArguments,
MainchainGovernanceAdminConfig,
MaintenanceArguments,
MaintenanceConfig,
Network,
RoninTrustedOrganizationArguments,
RoninTrustedOrganizationConfig,
RoninValidatorSetArguments,
RoninValidatorSetConfig,
SlashIndicatorArguments,
SlashIndicatorConfig,
StakingArguments,
StakingConfig,
StakingVestingArguments,
StakingVestingConfig,
} from './utils';

export const commonNetworks: LiteralNetwork[] = [Network.Hardhat, Network.Devnet];
export const commonNetworks: LiteralNetwork[] = [Network.Local, Network.Hardhat, Network.Devnet];
export const mainchainNetworks: LiteralNetwork[] = [...commonNetworks, Network.Goerli, Network.Ethereum];
export const roninchainNetworks: LiteralNetwork[] = [...commonNetworks, Network.Testnet, Network.Mainnet];
export const allNetworks: LiteralNetwork[] = [
Expand All @@ -24,139 +31,148 @@ export const allNetworks: LiteralNetwork[] = [

export const defaultAddress = '0x0000000000000000000000000000000000000000';

const defaultGeneralConf = {
startedAtBlock: 0,
bridgeContract: ethers.constants.AddressZero,
};

export const generalRoninConf: GeneralConfig = {
[Network.Hardhat]: {
startedAtBlock: 0,
bridgeContract: ethers.constants.AddressZero,
},
[Network.Devnet]: {
startedAtBlock: 0,
bridgeContract: ethers.constants.AddressZero,
},
[Network.Local]: defaultGeneralConf,
[Network.Hardhat]: defaultGeneralConf,
[Network.Devnet]: defaultGeneralConf,
};

export const generalMainchainConf: GeneralConfig = {
[Network.Hardhat]: {
startedAtBlock: 0,
bridgeContract: ethers.constants.AddressZero,
},
[Network.Devnet]: {
startedAtBlock: 0,
bridgeContract: ethers.constants.AddressZero,
},
[Network.Local]: defaultGeneralConf,
[Network.Hardhat]: defaultGeneralConf,
[Network.Devnet]: defaultGeneralConf,
};

const defaultMaintenanceConf: MaintenanceArguments = {
minMaintenanceBlockPeriod: 600, // 600 blocks
maxMaintenanceBlockPeriod: 28800, // ~1 day
minOffset: 28800, // requests before maintaining at least ~1 day
maxSchedules: 3, // only 3 schedules are happening|in the futures
};

// TODO: update config for testnet & mainnet
export const maintenanceConf: MaintenanceConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
minMaintenanceBlockPeriod: 600, // 600 blocks
maxMaintenanceBlockPeriod: 28800, // ~1 day
minOffset: 28800, // requests before maintaining at least ~1 day
maxSchedules: 3, // only 3 schedules are happening|in the futures
},
[Network.Local]: defaultMaintenanceConf,
[Network.Devnet]: defaultMaintenanceConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
};

const defaultStakingConf: StakingArguments = {
minValidatorStakingAmount: BigNumber.from(10).pow(18).mul(BigNumber.from(10).pow(5)), // 100.000 RON
cooldownSecsToUndelegate: 3 * 86400, // at least 3 days
waitingSecsToRevoke: 7 * 86400, // at least 7 days
};

// TODO: update config for testnet & mainnet
export const stakingConfig: StakingConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
minValidatorStakingAmount: BigNumber.from(10).pow(18).mul(BigNumber.from(10).pow(5)), // 100.000 RON
cooldownSecsToUndelegate: 3 * 86400, // at least 3 days
waitingSecsToRevoke: 7 * 86400, // at least 7 days
},
[Network.Local]: defaultStakingConf,
[Network.Devnet]: defaultStakingConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
};

const defaultStakingVestingConf: StakingVestingArguments = {
blockProducerBonusPerBlock: BigNumber.from(10).pow(18), // 1 RON per block
bridgeOperatorBonusPerBlock: BigNumber.from(10).pow(18), // 1 RON per block
topupAmount: BigNumber.from(10).pow(18).mul(BigNumber.from(10).pow(4)), // 10.000 RON
};

// TODO: update config for testnet & mainnet
export const stakingVestingConfig: StakingVestingConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
blockProducerBonusPerBlock: BigNumber.from(10).pow(18), // 1 RON per block
bridgeOperatorBonusPerBlock: BigNumber.from(10).pow(18), // 1 RON per block
topupAmount: BigNumber.from(10).pow(18).mul(BigNumber.from(10).pow(4)), // 10.000 RON
},
[Network.Local]: defaultStakingVestingConf,
[Network.Devnet]: defaultStakingVestingConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
};

const defaultSlashIndicatorConf: SlashIndicatorArguments = {
bridgeOperatorSlashing: {
missingVotesRatioTier1: 10_00, // 10%
missingVotesRatioTier2: 20_00, // 20%
jailDurationForMissingVotesRatioTier2: 28800 * 2, // jails for 2 days
},
bridgeVotingSlashing: {
bridgeVotingThreshold: 28800 * 3, // ~3 days
bridgeVotingSlashAmount: BigNumber.from(10).pow(18).mul(10_000), // 10.000 RON
},
doubleSignSlashing: {
slashDoubleSignAmount: BigNumber.from(10).pow(18).mul(10), // 10 RON
doubleSigningJailUntilBlock: ethers.constants.MaxUint256,
},
unavailabilitySlashing: {
unavailabilityTier1Threshold: 50,
unavailabilityTier2Threshold: 150,
slashAmountForUnavailabilityTier2Threshold: BigNumber.from(10).pow(18).mul(1), // 1 RON
jailDurationForUnavailabilityTier2Threshold: 2 * 28800, // jails for 2 days
},
creditScore: {
gainCreditScore: 50,
maxCreditScore: 600,
bailOutCostMultiplier: 5,
cutOffPercentageAfterBailout: 50_00, // 50%
},
};

// TODO: update config for testnet & mainnet
export const slashIndicatorConf: SlashIndicatorConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
bridgeOperatorSlashing: {
missingVotesRatioTier1: 10_00, // 10%
missingVotesRatioTier2: 20_00, // 20%
jailDurationForMissingVotesRatioTier2: 28800 * 2, // jails for 2 days
},
bridgeVotingSlashing: {
bridgeVotingThreshold: 28800 * 3, // ~3 days
bridgeVotingSlashAmount: BigNumber.from(10).pow(18).mul(10_000), // 10.000 RON
},
doubleSignSlashing: {
slashDoubleSignAmount: BigNumber.from(10).pow(18).mul(10), // 10 RON
doubleSigningJailUntilBlock: ethers.constants.MaxUint256,
},
unavailabilitySlashing: {
unavailabilityTier1Threshold: 50,
unavailabilityTier2Threshold: 150,
slashAmountForUnavailabilityTier2Threshold: BigNumber.from(10).pow(18).mul(1), // 1 RON
jailDurationForUnavailabilityTier2Threshold: 2 * 28800, // jails for 2 days
},
creditScore: {
gainCreditScore: 50,
maxCreditScore: 600,
bailOutCostMultiplier: 5,
cutOffPercentageAfterBailout: 50_00, // 50%
},
},
[Network.Local]: defaultSlashIndicatorConf,
[Network.Devnet]: defaultSlashIndicatorConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
};

const defaultRoninValidatorSetConf: RoninValidatorSetArguments = {
maxValidatorNumber: 21,
maxPrioritizedValidatorNumber: 11,
maxValidatorCandidate: 100,
numberOfBlocksInEpoch: 600,
};

// TODO: update config for testnet & mainnet
export const roninValidatorSetConf: RoninValidatorSetConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
maxValidatorNumber: 21,
maxPrioritizedValidatorNumber: 11,
maxValidatorCandidate: 100,
numberOfBlocksInEpoch: 600,
},
[Network.Local]: defaultRoninValidatorSetConf,
[Network.Devnet]: defaultRoninValidatorSetConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
};

// TODO: update config for testnet, mainnet, goerli, ethereum
const defaultRoninTrustedOrganizationConf: RoninTrustedOrganizationArguments = {
trustedOrganizations: ['0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1'].map((addr) => ({
consensusAddr: addr,
governor: addr,
bridgeVoter: addr,
weight: 100,
addedBlock: 0,
})),
numerator: 0,
denominator: 1,
};

// TODO: update config for testnet vs. goerli, mainnet vs. ethereum
export const roninTrustedOrganizationConf: RoninTrustedOrganizationConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
trustedOrganizations: ['0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1'].map((addr) => ({
consensusAddr: addr,
governor: addr,
bridgeVoter: addr,
weight: 100,
addedBlock: 0,
})),
numerator: 0,
denominator: 1,
},
[Network.Local]: defaultRoninTrustedOrganizationConf,
[Network.Devnet]: defaultRoninTrustedOrganizationConf,
[Network.Testnet]: undefined,
[Network.Mainnet]: undefined,
[Network.Goerli]: undefined,
[Network.Ethereum]: undefined,
};

const defaultMainchainGovernanceAdminConf: MainchainGovernanceAdminArguments = {
roleSetter: '0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1',
relayers: ['0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1'],
};

// TODO: update config for goerli, ethereum
export const mainchainGovernanceAdminConf: MainchainGovernanceAdminConfig = {
[Network.Hardhat]: undefined,
[Network.Devnet]: {
roleSetter: '0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1',
relayers: ['0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1'],
},
[Network.Local]: defaultMainchainGovernanceAdminConf,
[Network.Devnet]: defaultMainchainGovernanceAdminConf,
[Network.Goerli]: undefined,
[Network.Ethereum]: undefined,
};
6 changes: 6 additions & 0 deletions src/deploy/calculate-address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ethers, network } from 'hardhat';
import { HardhatRuntimeEnvironment } from 'hardhat/types';

import { generalRoninConf, roninchainNetworks, mainchainNetworks, generalMainchainConf } from '../config';
import { Network } from '../utils';

const calculateAddress = (from: string, nonce: number) => ({
nonce,
Expand Down Expand Up @@ -33,6 +34,10 @@ const deploy = async ({ getNamedAccounts }: HardhatRuntimeEnvironment) => {
roninTrustedOrganizationContract: calculateAddress(deployer, nonce++),
};
}

if ([Network.Local.toString()].includes(network.name)) {
generalMainchainConf[network.name].bridgeContract = calculateAddress(deployer, nonce++).address;
}
};

deploy.tags = ['CalculateAddresses'];
Expand All @@ -44,6 +49,7 @@ deploy.dependencies = [
'RoninValidatorSetLogic',
'RoninTrustedOrganizationLogic',
'BridgeTrackingLogic',
'MainchainGatewayV2Logic', // only for local
];

export default deploy;
23 changes: 23 additions & 0 deletions src/deploy/logic/mainchain-gateway-v2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { network } from 'hardhat';
import { HardhatRuntimeEnvironment } from 'hardhat/types';

import { Network } from '../../utils';

const deploy = async ({ getNamedAccounts, deployments }: HardhatRuntimeEnvironment) => {
if (![Network.Local.toString()].includes(network.name!)) {
return;
}

const { deploy } = deployments;
const { deployer } = await getNamedAccounts();

await deploy('MainchainGatewayV2Logic', {
contract: 'MainchainGatewayV2',
from: deployer,
log: true,
});
};

deploy.tags = ['MainchainGatewayV2Logic'];

export default deploy;
Loading

0 comments on commit d6ac960

Please sign in to comment.