Skip to content

Commit

Permalink
setup notifier and token rater oracle after deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
kovalgek committed Jul 5, 2024
1 parent 57e61ea commit 7da0c78
Show file tree
Hide file tree
Showing 6 changed files with 358 additions and 42 deletions.
21 changes: 18 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,30 @@ ACCOUNTING_ORACLE=
# l2GasLimit = (gas cost of L2Bridge.finalizeDeposit() + OptimismPortal.minimumGasLimit(depositData.length)) * 1.5
L2_GAS_LIMIT_FOR_PUSHING_TOKEN_RATE=

# Address of L1 token bridge proxy. Should be provided only for upgrade.
# Address of L1 token bridge proxy.
L1_TOKEN_BRIDGE=

# Address of Lido Core protocol contract
LIDO=

# Account that is allowed to add or remove pushers.
TOKEN_RATE_NOTIFIER_OWNER=

############ L2 Part
###### TokenRateOracle params

# Address of the account to grant the DEFAULT_ADMIN_ROLE
TOKEN_RATE_ORACLE_ADMIN=

# Enable token rate orace updates
TOKEN_RATE_UPDATE_ENABLED=

# Roles granting the permission to pause updating rate.
TOKEN_RATE_UPDATE_DISABLERS=

# Roles granting the permission to resume updating rate.
TOKEN_RATE_UPDATE_ENABLERS=

# A time period when token rate can be considered outdated. Default is 86400 (24 hours)
TOKEN_RATE_OUTDATED_DELAY=

Expand All @@ -64,10 +79,10 @@ OLDEST_RATE_ALLOWED_IN_PAUSE_TIME_SPAN=
MIN_TIME_BETWEEN_TOKEN_RATE_UPDATES=

# Initial wstETH/stETH token rate, uses 10**27 precision.
TOKEN_RATE=
INITIAL_TOKEN_RATE_VALUE=

# Initial L1 time when rate was updated on L1 side.
TOKEN_RATE_L1_TIMESTAMP=
INITIAL_TOKEN_RATE_L1_TIMESTAMP=

###### L2 wstETH Token.
# Address of the L2 non-rebasable token (L2 wstETH) proxy on L2. Should be provided only for upgrade.
Expand Down
30 changes: 18 additions & 12 deletions scripts/optimism/deploy-scratch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import network from "../../utils/network";
import deployment from "../../utils/deployment";
import { BridgingManagement } from "../../utils/bridging-management";
import deploymentAll from "../../utils/optimism/deployment";
import { TokenRateNotifier__factory } from "../../typechain";
import { TokenRateNotifierManagement } from "../../utils/tokenRateNotifier-management";

async function main() {
const networkName = env.network();
Expand All @@ -13,6 +13,11 @@ async function main() {
const [ethDeployer] = ethOptNetwork.getSigners(env.privateKey(), {
forking: env.forking()
});

const [ethProvider] = ethOptNetwork.getProviders({
forking: env.forking()
});

const [, optDeployer] = ethOptNetwork.getSigners(
env.string("OPT_DEPLOYER_PRIVATE_KEY"),
{
Expand All @@ -30,6 +35,7 @@ async function main() {
accountingOracle: deploymentConfig.accountingOracle,
l2GasLimitForPushingTokenRate: deploymentConfig.l2GasLimitForPushingTokenRate,
lido: deploymentConfig.lido,

deployer: ethDeployer,
admins: {
proxy: deploymentConfig.l1.proxyAdmin,
Expand All @@ -44,8 +50,8 @@ async function main() {
maxAllowedTokenRateDeviationPerDayBp: deploymentConfig.maxAllowedTokenRateDeviationPerDayBp,
oldestRateAllowedInPauseTimeSpan: deploymentConfig.oldestRateAllowedInPauseTimeSpan,
minTimeBetweenTokenRateUpdates: deploymentConfig.minTimeBetweenTokenRateUpdates,
tokenRate: deploymentConfig.tokenRateValue,
l1Timestamp: deploymentConfig.tokenRateL1Timestamp
tokenRate: deploymentConfig.initialTokenRateValue,
l1Timestamp: deploymentConfig.initialTokenRateL1Timestamp
},
l2TokenNonRebasable: {
version: deploymentConfig.l2TokenNonRebasableVersion
Expand Down Expand Up @@ -77,17 +83,17 @@ async function main() {
await l1DeployScript.run();
await l2DeployScript.run();

const [ethProvider, ] = ethOptNetwork.getProviders({
forking: env.forking()
});

const tokenRateNotifier = TokenRateNotifier__factory.connect(
const tokenRateNotifierManagement = new TokenRateNotifierManagement(
l1DeployScript.tokenRateNotifierImplAddress,
ethProvider
ethDeployer
);
await tokenRateNotifier
.connect(ethDeployer)
.addObserver(l1DeployScript.opStackTokenRatePusherImplAddress);
await tokenRateNotifierManagement.setup({
tokenRateNotifier: l1DeployScript.tokenRateNotifierImplAddress,
opStackTokenRatePusher: l1DeployScript.opStackTokenRatePusherImplAddress,
ethDeployer: ethDeployer,
ethProvider: ethProvider,
notifierOwner: deploymentConfig.tokenRateNotifierOwner
});

const l1BridgingManagement = new BridgingManagement(
l1DeployScript.bridgeProxyAddress,
Expand Down
51 changes: 28 additions & 23 deletions scripts/optimism/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import env from "../../utils/env";
import prompt from "../../utils/prompt";
import network from "../../utils/network";
import deployment from "../../utils/deployment";
import { BridgingManagement } from "../../utils/bridging-management";
import { TokenRateNotifierManagement } from "../../utils/tokenRateNotifier-management";
import { TokenRateOracleManagement } from "../../utils/tokenRateOracle-management";
import upgrade from "../../utils/optimism/upgrade";
import { TokenRateNotifier__factory } from "../../typechain";

async function main() {
const networkName = env.network();
Expand All @@ -13,6 +13,10 @@ async function main() {
const [ethDeployer] = ethOptNetwork.getSigners(env.privateKey(), {
forking: env.forking(),
});
const [ethProvider] = ethOptNetwork.getProviders({
forking: env.forking()
});

const [, optDeployer] = ethOptNetwork.getSigners(
env.string("OPT_DEPLOYER_PRIVATE_KEY"),
{
Expand Down Expand Up @@ -49,8 +53,8 @@ async function main() {
minTimeBetweenTokenRateUpdates: deploymentConfig.minTimeBetweenTokenRateUpdates
},
initialize: {
tokenRate: deploymentConfig.tokenRateValue,
l1Timestamp: deploymentConfig.tokenRateL1Timestamp
tokenRate: deploymentConfig.initialTokenRateValue,
l1Timestamp: deploymentConfig.initialTokenRateL1Timestamp
}
},
l2TokenBridge: deploymentConfig.l2TokenBridge,
Expand Down Expand Up @@ -85,33 +89,34 @@ async function main() {
await l1DeployScript.run();
await l2DeployScript.run();

// add observer
// TODO: transferOwnership to Agent
const [ethProvider, ] = ethOptNetwork.getProviders({
forking: env.forking()
});
const tokenRateNotifier = TokenRateNotifier__factory.connect(
/// Setup TokenRateNotifier
const tokenRateNotifierManagement = new TokenRateNotifierManagement(
l1DeployScript.tokenRateNotifierImplAddress,
ethProvider
);
await tokenRateNotifier
.connect(ethDeployer)
.addObserver(l1DeployScript.opStackTokenRatePusherImplAddress);

const l1BridgingManagement = new BridgingManagement(
l1DeployScript.bridgeProxyAddress,
ethDeployer,
{ logger: console }
);
await tokenRateNotifierManagement.setup({
tokenRateNotifier: l1DeployScript.tokenRateNotifierImplAddress,
opStackTokenRatePusher: l1DeployScript.opStackTokenRatePusherImplAddress,
ethDeployer: ethDeployer,
ethProvider: ethProvider,
notifierOwner: deploymentConfig.tokenRateNotifierOwner
});

const l2BridgingManagement = new BridgingManagement(
l2DeployScript.tokenBridgeProxyAddress,
/// Setup TokenRateOracle
const tokenRateOracleManagement = new TokenRateOracleManagement(
l2DeployScript.tokenRateOracleProxyAddress,
optDeployer,
{ logger: console }
);

await l1BridgingManagement.setup(deploymentConfig.l1);
await l2BridgingManagement.setup(deploymentConfig.l2);
await tokenRateOracleManagement.setup({
tokenRateOracleAdmin: deploymentConfig. tokenRateOracleAdmin,
initialTokenRateValue: deploymentConfig.initialTokenRateValue,
initialTokenRateL1Timestamp: deploymentConfig.initialTokenRateL1Timestamp,
rateUpdatesEnabled: deploymentConfig.tokenRateUpdateEnabled,
rateUpdatesDisablers: deploymentConfig.tokenRateUpdateDisablers,
rateUpdatesEnablers: deploymentConfig.tokenRateUpdateEnablers
});
}

main().catch((error) => {
Expand Down
20 changes: 16 additions & 4 deletions utils/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@ interface MultiChainDeploymentConfig {
l2GasLimitForPushingTokenRate: BigNumber;
l1TokenBridge: string;
lido: string;
tokenRateNotifierOwner: string;

/// L2
/// Oracle
tokenRateOracleAdmin: string;
tokenRateUpdateEnabled: boolean;
tokenRateUpdateDisablers?: string[],
tokenRateUpdateEnablers?: string[],

tokenRateOutdatedDelay: BigNumber;
maxAllowedL2ToL1ClockLag: BigNumber;
maxAllowedTokenRateDeviationPerDayBp: BigNumber;
oldestRateAllowedInPauseTimeSpan: BigNumber;
minTimeBetweenTokenRateUpdates: BigNumber;
tokenRateValue: BigNumber;
tokenRateL1Timestamp: BigNumber;
initialTokenRateValue: BigNumber;
initialTokenRateL1Timestamp: BigNumber;

/// L2 wstETH address to upgrade
l2TokenNonRebasableAddress: string;
Expand All @@ -52,16 +58,22 @@ export function loadMultiChainDeploymentConfig(): MultiChainDeploymentConfig {
l2GasLimitForPushingTokenRate: BigNumber.from(env.string("L2_GAS_LIMIT_FOR_PUSHING_TOKEN_RATE")),
l1TokenBridge: env.address("L1_TOKEN_BRIDGE"),
lido: env.address("LIDO"),
tokenRateNotifierOwner: env.address("TOKEN_RATE_NOTIFIER_OWNER"),

/// L2 Part
/// TokenRateOracle
tokenRateOracleAdmin: env.address("TOKEN_RATE_ORACLE_ADMIN"),
tokenRateUpdateEnabled: env.bool("TOKEN_RATE_UPDATE_ENABLED", true),
tokenRateUpdateDisablers: env.addresses("TOKEN_RATE_UPDATE_DISABLERS", []),
tokenRateUpdateEnablers: env.addresses("TOKEN_RATE_UPDATE_ENABLERS", []),

tokenRateOutdatedDelay: BigNumber.from(env.string("TOKEN_RATE_OUTDATED_DELAY")),
maxAllowedL2ToL1ClockLag: BigNumber.from(env.string("MAX_ALLOWED_L2_TO_L1_CLOCK_LAG")),
maxAllowedTokenRateDeviationPerDayBp: BigNumber.from(env.string("MAX_ALLOWED_TOKEN_RATE_DEVIATION_PER_DAY_BP")),
oldestRateAllowedInPauseTimeSpan: BigNumber.from(env.string("OLDEST_RATE_ALLOWED_IN_PAUSE_TIME_SPAN")),
minTimeBetweenTokenRateUpdates: BigNumber.from(env.string("MIN_TIME_BETWEEN_TOKEN_RATE_UPDATES")),
tokenRateValue: BigNumber.from(env.string("TOKEN_RATE")),
tokenRateL1Timestamp: BigNumber.from(env.string("TOKEN_RATE_L1_TIMESTAMP")),
initialTokenRateValue: BigNumber.from(env.string("INITIAL_TOKEN_RATE_VALUE")),
initialTokenRateL1Timestamp: BigNumber.from(env.string("INITIAL_TOKEN_RATE_L1_TIMESTAMP")),

// L2 wstETH
l2TokenNonRebasableAddress: env.address("L2_TOKEN_NON_REBASABLE"),
Expand Down
81 changes: 81 additions & 0 deletions utils/tokenRateNotifier-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

import { Signer, Wallet } from "ethers";
import { TokenRateNotifier, TokenRateNotifier__factory } from "../typechain";
import { JsonRpcProvider } from "@ethersproject/providers";
import chalk from "chalk";

interface Logger {
log(message: string): void;
}

export interface TokenRateNotifierSetupConfig {
tokenRateNotifier: string;
opStackTokenRatePusher: string;
ethDeployer: Wallet;
ethProvider: JsonRpcProvider;
notifierOwner: string;
}

export class TokenRateNotifierManagement {

public readonly tokenRateNotifier: TokenRateNotifier;
private readonly logger: TokenRateNotifierManagementLogger;

constructor(
address: string,
admin: Wallet | Signer,
options: { logger?: Logger } = {}
) {
this.tokenRateNotifier = TokenRateNotifier__factory.connect(address, admin);
this.logger = new TokenRateNotifierManagementLogger(options?.logger);
}

async setup(config: TokenRateNotifierSetupConfig) {
const tokenRateNotifier = TokenRateNotifier__factory.connect(
config.tokenRateNotifier,
config.ethProvider
);
await tokenRateNotifier
.connect(config.ethDeployer)
.addObserver(config.opStackTokenRatePusher);

this.logger.logAddObserver(config);
this.logger.logStepDone();

await this.tokenRateNotifier.transferOwnership(config.notifierOwner);

this.logger.logTransferOwnership(config);
this.logger.logStepDone();
}
}

class TokenRateNotifierManagementLogger {
private readonly logger?: Logger;
constructor(logger?: Logger) {
this.logger = logger;
}

logAddObserver(config: TokenRateNotifierSetupConfig) {
this.logger?.log(`Add observer to Notifier:`);
this.logger?.log(
` ${chalk.cyan.italic("· notifier")} ${chalk.green(config.tokenRateNotifier)}`
);
this.logger?.log(
` ${chalk.cyan.italic("· observer")} ${chalk.green(config.opStackTokenRatePusher)}`
);
}

logTransferOwnership(config: TokenRateNotifierSetupConfig) {
this.logger?.log(`Transfer Notifier ownership:`);
this.logger?.log(
` ${chalk.cyan.italic("· from")} ${chalk.green(config.ethDeployer.address)}`
);
this.logger?.log(
` ${chalk.cyan.italic("· to")} ${chalk.green(config.notifierOwner)}`
);
}

logStepDone() {
this.logger?.log(`[${chalk.greenBright("DONE")}]\n`);
}
}
Loading

0 comments on commit 7da0c78

Please sign in to comment.