Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multisig-owned facade #1205

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ interface INetworkConfig {
AAVE_V3_POOL?: string
STARGATE_STAKING_CONTRACT?: string
CURVE_POOL_WETH_FRXETH?: string
DEV_MULTISIG?: string
}

export const networkConfig: { [key: string]: INetworkConfig } = {
Expand Down Expand Up @@ -308,6 +309,7 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
AAVE_V3_INCENTIVES_CONTROLLER: '0x8164Cc65827dcFe994AB23944CBC90e0aa80bFcb',
STARGATE_STAKING_CONTRACT: '0xB0D502E938ed5f4df2E681fE6E419ff29631d62b',
CURVE_POOL_WETH_FRXETH: '0x9c3b46c0ceb5b9e304fcd6d88fc50f7dd24b31bc',
DEV_MULTISIG: '0xf8A981f5D79a204835B5a105CEe54E176012a633', // same on all networks
},
'3': {
name: 'tenderly',
Expand Down Expand Up @@ -541,6 +543,7 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
AAVE_V3_POOL: '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5',
AAVE_V3_INCENTIVES_CONTROLLER: '0xf9cc4F0D883F1a1eb2c253bdb46c254Ca51E1F44',
STARGATE_STAKING_CONTRACT: '0x06Eb48763f117c7Be887296CDcdfad2E4092739C',
DEV_MULTISIG: '0xf8A981f5D79a204835B5a105CEe54E176012a633', // same on all networks
},
'42161': {
name: 'arbitrum',
Expand Down Expand Up @@ -581,6 +584,7 @@ export const networkConfig: { [key: string]: INetworkConfig } = {
COMET_EXT: '0x1B2E88cC7365d90e7E81392432482925BD8437E9',
AAVE_V3_POOL: '0x794a61358D6845594F94dc1DB02A252b5b4814aD',
AAVE_V3_INCENTIVES_CONTROLLER: '0x929EC64c34a17401F460460D4B9390518E5B473e',
DEV_MULTISIG: '0xf8A981f5D79a204835B5a105CEe54E176012a633', // same on all networks
},
'421614': {
name: 'arbitrum-sepolia',
Expand Down
4 changes: 3 additions & 1 deletion contracts/facade/Facade.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
mapping(bytes4 => address) public facets;

// solhint-disable-next-line no-empty-blocks
constructor() Ownable() {}
constructor(address owner) Ownable() {
_transferOwnership(owner);
}

// Save new facets to the Facade, forcefully
function save(address facet, bytes4[] memory selectors) external onlyOwner {
Expand All @@ -27,12 +29,12 @@

// Find the facet for function that is called and execute the
// function if a facet is found and return any value.
fallback() external {

Check warning on line 32 in contracts/facade/Facade.sol

View workflow job for this annotation

GitHub Actions / Lint Checks

When fallback is not payable you will not be able to receive ether

Check warning on line 32 in contracts/facade/Facade.sol

View workflow job for this annotation

GitHub Actions / Lint Checks

Fallback function must be simple
address facet = facets[msg.sig];
require(facet != address(0), "facet does not exist");

// Execute external function from facet using delegatecall and return any value.
assembly {

Check warning on line 37 in contracts/facade/Facade.sol

View workflow job for this annotation

GitHub Actions / Lint Checks

Avoid to use inline assembly. It is acceptable only in rare cases
// copy function selector and any arguments
calldatacopy(0, 0, calldatasize())
// execute function call using the facet
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
"@openzeppelin/contracts": "4.9.6",
"@openzeppelin/contracts-upgradeable": "4.9.6",
"@openzeppelin/hardhat-upgrades": "^1.23.0",
"@safe-global/api-kit": "^2.4.5",
"@safe-global/protocol-kit": "^4.1.0",
"@tenderly/hardhat-tenderly": "^1.7.7",
"@typechain/ethers-v5": "^7.2.0",
"@typechain/hardhat": "^2.3.1",
Expand Down
6 changes: 4 additions & 2 deletions scripts/addresses/1-tmp-assets-collateral.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
"sfrxETH": "0x4c891fCa6319d492866672E3D2AfdAAA5bDcfF67",
"ETHx": "0x73a36258E6A48D0095D1997Fec7F51e191B4Ec81",
"apxETH": "0x05ffDaAA2aF48e1De1CE34d633db018a28e3B3F5",
"sUSDe": "0x35081Ca24319835e5f759163F7e75eaB753e0b7E"
"sUSDe": "0x35081Ca24319835e5f759163F7e75eaB753e0b7E",
"pyUSD": "0xa5cde4fB1132daF8f4a0D3140859271208d944E9"
},
"erc20s": {
"stkAAVE": "0x4da27a545c0c5B758a6BA100e3a049001de870f5",
Expand Down Expand Up @@ -123,6 +124,7 @@
"CVX": "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B",
"ETHx": "0xA35b1B31Ce002FBF2058D22F30f95D405200A15b",
"apxETH": "0x9Ba021B0a9b958B5E75cE9f6dff97C7eE52cb3E6",
"sUSDe": "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497"
"sUSDe": "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497",
"pyUSD": "0x6c3ea9036406852006290770bedfcaba0e23a0e8"
}
}
3 changes: 2 additions & 1 deletion scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ async function main() {
'phase2-assets/collaterals/deploy_apxeth.ts',
'phase2-assets/collaterals/deploy_USDe.ts',
'phase2-assets/assets/deploy_crv.ts',
'phase2-assets/assets/deploy_cvx.ts'
'phase2-assets/assets/deploy_cvx.ts',
'phase2-assets/collaterals/deploy_pyusd.ts'
)
} else if (chainId == '8453' || chainId == '84531') {
// Base L2 chains
Expand Down
6 changes: 5 additions & 1 deletion scripts/deployment/phase1-core/4_deploy_facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ async function main() {
throw new Error(`RSR Asset contract not found in network ${hre.network.name}`)
}

if (!networkConfig[chainId].DEV_MULTISIG) {
throw new Error(`Missing DEV_MULTISIG address in network ${hre.network.name}`)
}

// ******************** Deploy Facade ****************************************/

const FacadeFactory = await ethers.getContractFactory('Facade')
facade = <Facade>await FacadeFactory.connect(burner).deploy()
facade = <Facade>await FacadeFactory.connect(burner).deploy(networkConfig[chainId].DEV_MULTISIG)
await facade.deployed()

// Write temporary deployments file
Expand Down
22 changes: 15 additions & 7 deletions scripts/deployment/phase1-facade/1_deploy_readFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import hre, { ethers } from 'hardhat'
import { getChainId, isValidContract } from '../../../common/blockchain-utils'
import { networkConfig } from '../../../common/configuration'
import { getDeploymentFile, getDeploymentFilename, IDeployments } from '../common'
import { initiateMultisigTx } from '../utils'
import { ReadFacet } from '../../../typechain'

import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'

let readFacet: ReadFacet

async function main() {
Expand Down Expand Up @@ -47,16 +50,21 @@ async function main() {

// ******************** Save to Facade ****************************************/

console.log('Configuring with Facade...')
console.log('Configuring with Facade via multisig...')

// Save ReadFacet to Facade
// Save ReadFacet functions to Facade
const facade = await ethers.getContractAt('Facade', deployments.facade)
await facade.save(
readFacet.address,
Object.entries(readFacet.functions).map(([fn]) => readFacet.interface.getSighash(fn))
)

console.log('Finished saving to Facade')
const tx: MetaTransactionData = {
to: facade.address,
value: '0',
data: facade.interface.encodeFunctionData('save', [
readFacet.address,
Object.entries(readFacet.functions).map(([fn]) => readFacet.interface.getSighash(fn)),
]),
}

await initiateMultisigTx(chainId, tx)
}

main().catch((error) => {
Expand Down
20 changes: 14 additions & 6 deletions scripts/deployment/phase1-facade/2_deploy_actFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import hre, { ethers } from 'hardhat'
import { getChainId, isValidContract } from '../../../common/blockchain-utils'
import { networkConfig } from '../../../common/configuration'
import { getDeploymentFile, getDeploymentFilename, IDeployments } from '../common'
import { initiateMultisigTx } from '../utils'
import { ActFacet } from '../../../typechain'

import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'

let actFacet: ActFacet

async function main() {
Expand Down Expand Up @@ -49,14 +52,19 @@ async function main() {

console.log('Configuring with Facade...')

// Save ReadFacet to Facade
// Save ActFacet functions to Facade
const facade = await ethers.getContractAt('Facade', deployments.facade)
await facade.save(
actFacet.address,
Object.entries(actFacet.functions).map(([fn]) => actFacet.interface.getSighash(fn))
)

console.log('Finished saving to Facade')
const tx: MetaTransactionData = {
to: facade.address,
value: '0',
data: facade.interface.encodeFunctionData('save', [
actFacet.address,
Object.entries(actFacet.functions).map(([fn]) => actFacet.interface.getSighash(fn)),
]),
}

await initiateMultisigTx(chainId, tx)
}

main().catch((error) => {
Expand Down
24 changes: 16 additions & 8 deletions scripts/deployment/phase1-facade/3_deploy_maxIssuable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import hre, { ethers } from 'hardhat'
import { getChainId, isValidContract } from '../../../common/blockchain-utils'
import { networkConfig } from '../../../common/configuration'
import { getDeploymentFile, getDeploymentFilename, IDeployments } from '../common'
import { initiateMultisigTx } from '../utils'
import { MaxIssuableFacet } from '../../../typechain'

import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'

let maxIssuableFacet: MaxIssuableFacet

async function main() {
Expand Down Expand Up @@ -51,14 +54,19 @@ async function main() {

// Save MaxIssuableFacet functions to Facade
const facade = await ethers.getContractAt('Facade', deployments.facade)
await facade.save(
maxIssuableFacet.address,
Object.entries(maxIssuableFacet.functions).map(([fn]) =>
maxIssuableFacet.interface.getSighash(fn)
)
)

console.log('Finished saving to Facade')

const tx: MetaTransactionData = {
to: facade.address,
value: '0',
data: facade.interface.encodeFunctionData('save', [
maxIssuableFacet.address,
Object.entries(maxIssuableFacet.functions).map(([fn]) =>
maxIssuableFacet.interface.getSighash(fn)
),
]),
}

await initiateMultisigTx(chainId, tx)
}

main().catch((error) => {
Expand Down
24 changes: 16 additions & 8 deletions scripts/deployment/phase1-facade/4_deploy_backingBufferFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import hre, { ethers } from 'hardhat'
import { getChainId, isValidContract } from '../../../common/blockchain-utils'
import { networkConfig } from '../../../common/configuration'
import { getDeploymentFile, getDeploymentFilename, IDeployments } from '../common'
import { initiateMultisigTx } from '../utils'
import { BackingBufferFacet } from '../../../typechain'

import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'

let backingBufferFacet: BackingBufferFacet

async function main() {
Expand Down Expand Up @@ -51,14 +54,19 @@ async function main() {

// Save BackingBufferFacet functions to Facade
const facade = await ethers.getContractAt('Facade', deployments.facade)
await facade.save(
backingBufferFacet.address,
Object.entries(backingBufferFacet.functions).map(([fn]) =>
backingBufferFacet.interface.getSighash(fn)
)
)

console.log('Finished saving to Facade')

const tx: MetaTransactionData = {
to: facade.address,
value: '0',
data: facade.interface.encodeFunctionData('save', [
backingBufferFacet.address,
Object.entries(backingBufferFacet.functions).map(([fn]) =>
backingBufferFacet.interface.getSighash(fn)
),
]),
}

await initiateMultisigTx(chainId, tx)
}

main().catch((error) => {
Expand Down
18 changes: 13 additions & 5 deletions scripts/deployment/phase1-facade/5_deploy_revenueFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import hre, { ethers } from 'hardhat'
import { getChainId, isValidContract } from '../../../common/blockchain-utils'
import { networkConfig } from '../../../common/configuration'
import { getDeploymentFile, getDeploymentFilename, IDeployments } from '../common'
import { initiateMultisigTx } from '../utils'
import { RevenueFacet } from '../../../typechain'

import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'

let revenueFacet: RevenueFacet

async function main() {
Expand Down Expand Up @@ -51,12 +54,17 @@ async function main() {

// Save RevenueFacet functions to Facade
const facade = await ethers.getContractAt('Facade', deployments.facade)
await facade.save(
revenueFacet.address,
Object.entries(revenueFacet.functions).map(([fn]) => revenueFacet.interface.getSighash(fn))
)

console.log('Finished saving to Facade')
const tx: MetaTransactionData = {
to: facade.address,
value: '0',
data: facade.interface.encodeFunctionData('save', [
revenueFacet.address,
Object.entries(revenueFacet.functions).map(([fn]) => revenueFacet.interface.getSighash(fn)),
]),
}

await initiateMultisigTx(chainId, tx)
}

main().catch((error) => {
Expand Down
85 changes: 85 additions & 0 deletions scripts/deployment/phase2-assets/collaterals/deploy_pyusd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import fs from 'fs'
import hre, { ethers } from 'hardhat'
import { getChainId } from '../../../../common/blockchain-utils'
import { arbitrumL2Chains, baseL2Chains, networkConfig } from '../../../../common/configuration'
import { bn, fp } from '../../../../common/numbers'
import {
getDeploymentFile,
getDeploymentFilename,
getAssetCollDeploymentFilename,
IAssetCollDeployments,
fileExists,
} from '../../../deployment/common'
import { priceTimeout } from '../../../deployment/utils'
import { Asset, ICollateral } from '../../../../typechain'
import {
PYUSD_MAX_TRADE_VOLUME,
PYUSD_ORACLE_ERROR,
PYUSD_ORACLE_TIMEOUT,
} from '#/test/plugins/individual-collateral/aave-v3/constants'
import { CollateralStatus } from '#/common/constants'
import { expect } from 'chai'

async function main() {
// ==== Read Configuration ====
const [burner] = await hre.ethers.getSigners()
const chainId = await getChainId(hre)

console.log(`Deploying pyUSD asset to network ${hre.network.name} (${chainId})
with burner account: ${burner.address}`)

if (!networkConfig[chainId]) {
throw new Error(`Missing network configuration for ${hre.network.name}`)
}

// Only exists on Mainnet
if (baseL2Chains.includes(hre.network.name) || arbitrumL2Chains.includes(hre.network.name)) {
throw new Error(`Invalid network ${hre.network.name} - only available on Mainnet`)
}

// Get phase1 deployment
const phase1File = getDeploymentFilename(chainId)
if (!fileExists(phase1File)) {
throw new Error(`${phase1File} doesn't exist yet. Run phase 1`)
}
// Check previous step completed
const assetCollDeploymentFilename = getAssetCollDeploymentFilename(chainId)
const assetCollDeployments = <IAssetCollDeployments>getDeploymentFile(assetCollDeploymentFilename)

const deployedCollateral: string[] = []

let collateral: ICollateral

/******** Deploy pyUSD asset **************************/
const { collateral: pyUsdCollateral } = await hre.run('deploy-fiat-collateral', {
priceTimeout: priceTimeout.toString(),
priceFeed: networkConfig[chainId].chainlinkFeeds.pyUSD,
oracleError: PYUSD_ORACLE_ERROR.toString(),
tokenAddress: networkConfig[chainId].tokens.pyUSD,
maxTradeVolume: PYUSD_MAX_TRADE_VOLUME.toString(), // $500k,
oracleTimeout: PYUSD_ORACLE_TIMEOUT.toString(),
targetName: hre.ethers.utils.formatBytes32String('USD'),
defaultThreshold: fp('0.01').add(PYUSD_ORACLE_ERROR).toString(),
delayUntilDefault: bn('86400').toString(), // 24h
})
collateral = <ICollateral>await ethers.getContractAt('ICollateral', pyUsdCollateral)
await (await collateral.refresh()).wait()
expect(await collateral.status()).to.equal(CollateralStatus.SOUND)

assetCollDeployments.collateral.pyUSD = pyUsdCollateral
assetCollDeployments.erc20s.pyUSD = networkConfig[chainId].tokens.pyUSD
deployedCollateral.push(pyUsdCollateral.toString())

/**************************************************************/

fs.writeFileSync(assetCollDeploymentFilename, JSON.stringify(assetCollDeployments, null, 2))

console.log(`Deployed pyUSD asset to ${hre.network.name} (${chainId}):
New deployments: ${deployedCollateral}
Deployment file: ${assetCollDeploymentFilename}`)
}

main().catch((error) => {
console.error(error)
process.exitCode = 1
})
Loading
Loading