Skip to content

Commit

Permalink
feat: sim nova and arbos31 propdata
Browse files Browse the repository at this point in the history
* arbos31 sim

* feat: sim nova

* fix: type

* update propdata

* update propdata

---------

Co-authored-by: gzeon <[email protected]>
  • Loading branch information
godzillaba and gzeoneth authored Sep 30, 2024
1 parent 5eec303 commit 1cdd9e2
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 15 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ETHERSCAN_API_KEY=yourEtherscanApiKey
RPC_URL=yourRpcUrl
L1_RPC_URL=yourL1RpcUrl
ARB1_RPC_URL=https://arb1.arbitrum.io/rpc
NOVA_RPC_URL=https://nova.arbitrum.io/rpc
TENDERLY_ACCESS_TOKEN=yourTenderlyAccessToken
TENDERLY_USER=yourTenderlyOrgOrMeIfPersonal
TENDERLY_PROJECT_SLUG=yourTenderlyProjectSlug
Expand Down
1 change: 1 addition & 0 deletions checks/check-decode-calldata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ function findMatchingCall(from: string, calldata: string, calls: any[]): FluffyC
from = getAddress(from)
// removed check for from address because crosschain execution addresses are not known
const callMatches = (f: string, c: string) => c === calldata // && getAddress(f) === from
if (!calls || !calls.length) return null // Fix TypeError: calls is not iterable
for (const call of calls) {
if (callMatches(call.from, call.input)) return call
if (call.calls) {
Expand Down
14 changes: 10 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import dotenv from 'dotenv'
dotenv.config()
import { BigNumber, BigNumberish, Contract, constants } from 'ethers'
import { DAO_NAME, GOVERNOR_ADDRESS, SIM_NAME } from './utils/constants'
import { arb1provider, l1provider, provider } from './utils/clients/ethers'
import { arb1provider, novaprovider, l1provider, provider } from './utils/clients/ethers'
import { simulate } from './utils/clients/tenderly'
import {
AllCheckResults,
Expand Down Expand Up @@ -88,9 +88,13 @@ async function simRetryable(sr: SimulationResult, simname: string) {
const messages: {
inboxMessageEvent: EventArgs<InboxMessageDeliveredEvent>
bridgeMessageEvent: EventArgs<MessageDeliveredEvent>
chainId: 42161 | 42170
}[] = []
const arb1Inbox = (await getL2Network(arb1provider as any)).ethBridge.inbox.toLowerCase()
const novaInbox = (await getL2Network(novaprovider as any)).ethBridge.inbox.toLowerCase()
for (const bm of bridgeMessages) {
if (bm.inbox !== (await getL2Network(arb1provider as any)).ethBridge.inbox) continue // arb1 inbox
const chainId = bm.inbox.toLowerCase() === arb1Inbox ? 42161 : bm.inbox.toLowerCase() === novaInbox ? 42170 : 0
if (chainId === 0) continue // unknown inbox
const im = inboxMessages.filter((i) => i.messageNum.eq(bm.messageIndex))[0]
if (!im) {
throw new Error(
Expand All @@ -100,11 +104,12 @@ async function simRetryable(sr: SimulationResult, simname: string) {
messages.push({
inboxMessageEvent: im,
bridgeMessageEvent: bm,
chainId: chainId,
})
}
const simresults = []
let offset = 10000
for (const { inboxMessageEvent, bridgeMessageEvent } of messages) {
for (const { inboxMessageEvent, bridgeMessageEvent, chainId } of messages) {
if (bridgeMessageEvent.kind === InboxMessageKind.L1MessageType_submitRetryableTx) {
const parser = new SubmitRetryableMessageDataParser()
const parsedRetryable = parser.parse(inboxMessageEvent.data)
Expand All @@ -119,9 +124,10 @@ async function simRetryable(sr: SimulationResult, simname: string) {
values: [parsedRetryable.l2CallValue], // Array of values with each call.
signatures: [''], // Array of function signatures. Leave empty if generating calldata with ethers like we do here.
calldatas: [parsedRetryable.data], // Array of encoded calldatas.
description: `# This is a L2 Retryable Execution of simulation ${parentId.toString()} \n.`,
description: `# This is a L2(${chainId}) Retryable Execution of simulation ${parentId.toString()} \n.`,
parentId: parentId,
idoffset: offset,
chainId: chainId
}
offset += 10000
const { sim, proposal, latestBlock } = await simulate(l2tol1config)
Expand Down
41 changes: 41 additions & 0 deletions sims/arbcore-arbos31.sim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @notice Simulation configuration file for ArbOS31 Upgrade
*/
import { ethers } from 'ethers'
import { SimulationConfigNew } from '../types'

const ARBSYS = '0x0000000000000000000000000000000000000064'


// from https://github.com/ArbitrumFoundation/governance/pull/298
const scElectionUpgrade = {
arbSysSendTxToL1Args: {
l1Timelock: '0xE6841D92B0C345144506576eC13ECf5103aC7f49',
calldata:
'0x8f2a0bb000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000000e13fb8241eb0e976305ff5f40d43d783c08468da55f38eee093510e004f512aa000000000000000000000000000000000000000000000000000000000003f48000000000000000000000000000000000000000000000000000000000000000070000000000000000000000003fffbadaf827559da092217e474760e2b2c3cedd0000000000000000000000003fffbadaf827559da092217e474760e2b2c3cedd000000000000000000000000a723c008e76e379c55599d2e4d93879beafda79c000000000000000000000000a723c008e76e379c55599d2e4d93879beafda79c000000000000000000000000a723c008e76e379c55599d2e4d93879beafda79c000000000000000000000000a723c008e76e379c55599d2e4d93879beafda79c000000000000000000000000a723c008e76e379c55599d2e4d93879beafda79c00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000000841cff79cd00000000000000000000000019b715cf310c28c9020e53aaa11ce9df42e718b500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000841cff79cd000000000000000000000000658afc9d5ec4476fa6bb7033ea465f9901fbff2700000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f000000000000000000000000cf57572261c7c2bcf21ffd220ea7d1a27d40a82700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000841cff79cd000000000000000000000000af81c82ec98f86d0017d78cd66f1026f1a5cf1db00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f000000000000000000000000cf57572261c7c2bcf21ffd220ea7d1a27d40a82700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000841cff79cd000000000000000000000000b040b105a4a0c7a9cc290164accbc3285536832200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000c4448b71118c9071bcb9734a0eac55d18a15394900000000000000000000000086a02dd71363c440b21f4c0e5b2ad01ffe1a748200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000841cff79cd0000000000000000000000006dd43360d2a69bb9fffc5349f2511f2a3bcbc2da00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000c4448b71118c9071bcb9734a0eac55d18a15394900000000000000000000000086a02dd71363c440b21f4c0e5b2ad01ffe1a748200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000841cff79cd00000000000000000000000061703bf337341f2e09d96dd6488c2907718a8e2600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000c4448b71118c9071bcb9734a0eac55d18a15394900000000000000000000000086a02dd71363c440b21f4c0e5b2ad01ffe1a748200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000841cff79cd000000000000000000000000849e360a247132f961c9cbe95ba39106c72e126800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b147f40c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
},
}
const iface = new ethers.utils.Interface(['function sendTxToL1(address,bytes)'])
const calldata = iface.encodeFunctionData('sendTxToL1', [
scElectionUpgrade.arbSysSendTxToL1Args.l1Timelock,
scElectionUpgrade.arbSysSendTxToL1Args.calldata,
])

const call1 = {
target: ARBSYS,
calldata: calldata,
value: 0,
signature: '',
}

export const config: SimulationConfigNew = {
type: 'new',
daoName: 'ArbCore',
governorType: 'arb',
governorAddress: '0xf07ded9dc292157749b6fd268e37df6ea38395b9',
targets: [call1.target], // Array of targets to call.
values: [call1.value], // Array of values with each call.
signatures: [call1.signature], // Array of function signatures. Leave empty if generating calldata with ethers like we do here.
calldatas: [call1.calldata], // Array of encoded calldatas.
description: 'ArbOS31 Upgrade Simulation',
}
3 changes: 2 additions & 1 deletion types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface SimulationConfigArbRetryable extends SimulationConfigBase {
parentId: BigNumberish
idoffset: BigNumberish
from: string
chainId: 42161 | 42170
}

export type SimulationConfig =
Expand Down Expand Up @@ -176,7 +177,7 @@ type ContractObject = {
}

export type TenderlyPayload = {
network_id: '1' | '3' | '4' | '5' | '42' | '42161'
network_id: '1' | '3' | '4' | '5' | '42' | '42161' | '42170'
block_number?: number
transaction_index?: number
from: string
Expand Down
4 changes: 3 additions & 1 deletion utils/clients/ethers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { providers } from 'ethers'
import { RPC_URL, L1_RPC_URL, ARB1_RPC_URL } from '../constants'
import { RPC_URL, L1_RPC_URL, ARB1_RPC_URL, NOVA_RPC_URL } from '../constants'

export const provider = new providers.JsonRpcProvider(RPC_URL)
export const l1provider = new providers.JsonRpcProvider(L1_RPC_URL)
export const arb1provider = new providers.JsonRpcProvider(ARB1_RPC_URL)
export const novaprovider = new providers.JsonRpcProvider(NOVA_RPC_URL)

if ((await l1provider.getNetwork()).chainId !== 1) throw new Error('L1_RPC need to be Mainnet')
if ((await arb1provider.getNetwork()).chainId !== 42161) throw new Error('ARB1_RPC need to be Arbitrum')
if ((await novaprovider.getNetwork()).chainId !== 42170) throw new Error('NOVA_RPC need to be Nova')

console.log(`Your primary provider is connected to networkID ${(await provider.getNetwork()).chainId}`)
11 changes: 6 additions & 5 deletions utils/clients/tenderly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { hexStripZeros } from '@ethersproject/bytes'
import { HashZero, Zero } from '@ethersproject/constants'
import { keccak256 } from '@ethersproject/keccak256'
import { toUtf8Bytes } from '@ethersproject/strings'
import { l1provider, provider, arb1provider } from './ethers'
import { l1provider, provider, arb1provider, novaprovider } from './ethers'
import mftch, { FETCH_OPT } from 'micro-ftch'
// @ts-ignore
const fetchUrl = mftch.default
Expand Down Expand Up @@ -698,17 +698,18 @@ async function simulateArbitrumL2ToL1(config: SimulationConfigArbL2ToL1): Promis
// This function simulate the execution of a retryable ticket on Arbitrum
async function simulateArbitrumRetryable(config: SimulationConfigArbRetryable): Promise<SimulationResult> {
// --- Validate config ---
const { targets, values, calldatas, description, signatures, parentId, from } = config
const { targets, values, calldatas, description, signatures, parentId, from, chainId } = config
if (targets.length !== 1) throw new Error('targets must be length 1')
if (targets.length !== values.length) throw new Error('targets and values must be the same length')
if (targets.length !== calldatas.length) throw new Error('targets and calldatas must be the same length')

const target = targets[0]

// --- Get details about the proposal we're simulating ---
const network = await arb1provider.getNetwork()
const l2provider = chainId === 42161 ? arb1provider : novaprovider
const network = await l2provider.getNetwork()
const blockNumberToUse = (await getLatestBlock(network.chainId)) - 3 // subtracting a few blocks to ensure tenderly has the block
const latestBlock = await arb1provider.getBlock(blockNumberToUse)
const latestBlock = await l2provider.getBlock(blockNumberToUse)

const proposalId = BigNumber.from(parentId).add(config.idoffset)

Expand All @@ -735,7 +736,7 @@ async function simulateArbitrumRetryable(config: SimulationConfigArbRetryable):
const simTimestamp = BigNumber.from(latestBlock.timestamp + 1)

const simulationPayload: TenderlyPayload = {
network_id: '42161',
network_id: chainId === 42161 ? '42161' : '42170',
// this field represents the block state to simulate against, so we use the latest block number
block_number: latestBlock.number,
from: from,
Expand Down
2 changes: 2 additions & 0 deletions utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const ETHERSCAN_API_KEY: string = process.env.ETHERSCAN_API_KEY!
export const RPC_URL: string = process.env.RPC_URL!
export const L1_RPC_URL: string = process.env.L1_RPC_URL!
export const ARB1_RPC_URL: string = process.env.ARB1_RPC_URL!
export const NOVA_RPC_URL: string = process.env.NOVA_RPC_URL!
export const TENDERLY_ACCESS_TOKEN: string = process.env.TENDERLY_ACCESS_TOKEN!
export const TENDERLY_USER: string = process.env.TENDERLY_USER!
export const TENDERLY_PROJECT_SLUG: string = process.env.TENDERLY_PROJECT_SLUG!
Expand All @@ -15,6 +16,7 @@ if (!ETHERSCAN_API_KEY) throw new Error('ETHERSCAN_API_KEY is not defined')
if (!RPC_URL) throw new Error('RPC_URL is not defined')
if (!L1_RPC_URL) throw new Error('L1_RPC_URL is not defined')
if (!ARB1_RPC_URL) throw new Error('ARB1_RPC_URL is not defined')
if (!NOVA_RPC_URL) throw new Error('NOVA_RPC_URL is not defined')
if (!TENDERLY_ACCESS_TOKEN) throw new Error('TENDERLY_ACCESS_TOKEN is not defined')
if (!TENDERLY_USER) throw new Error('TENDERLY_USER is not defined')
if (!TENDERLY_PROJECT_SLUG) throw new Error('TENDERLY_PROJECT_SLUG is not defined')
Expand Down
4 changes: 2 additions & 2 deletions utils/contracts/erc20.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Contract } from 'ethers'
import { provider, arb1provider, l1provider } from '../clients/ethers'
import { provider, arb1provider, novaprovider, l1provider } from '../clients/ethers'
import { getAddress } from '@ethersproject/address'

const SAI = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'
Expand Down Expand Up @@ -30,7 +30,7 @@ export const SAI_ABI = [

export async function fetchTokenMetadata(address: string, chainid: string) {
const abi = getAddress(address) === SAI ? SAI_ABI : ERC20_ABI
const token = new Contract(address, abi, chainid === '42161' ? arb1provider : chainid === '1' ? l1provider : provider)
const token = new Contract(address, abi, chainid === '42161' ? arb1provider : chainid === '42170' ? novaprovider : chainid === '1' ? l1provider : provider)
const response = await Promise.all([token.name(), token.symbol(), token.decimals()])
return {
name: response[0] as string,
Expand Down
4 changes: 2 additions & 2 deletions utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defaultAbiCoder } from '@ethersproject/abi'
import { BigNumber, BigNumberish } from '@ethersproject/bignumber'
import { hexStripZeros, hexZeroPad } from '@ethersproject/bytes'
import { keccak256 } from '@ethersproject/keccak256'
import { arb1provider, l1provider } from '../utils/clients/ethers'
import { arb1provider, novaprovider, l1provider } from '../utils/clients/ethers'

/**
* @notice Returns the storage slot for a Solidity mapping with uint keys, given the slot of the mapping itself
Expand Down Expand Up @@ -34,5 +34,5 @@ export function to32ByteHexString(val: BigNumberish) {
}

export function getProvider(chainId: string) {
return chainId === '42161' ? arb1provider : l1provider
return chainId === '42161' ? arb1provider : chainId === '42170' ? novaprovider : l1provider
}

0 comments on commit 1cdd9e2

Please sign in to comment.