Skip to content

Commit 53b2723

Browse files
authored
Merge pull request #126 from aave/feat/defender-integration
Add OpenZeppelin Defender Integration
2 parents 2aeb420 + 83d2989 commit 53b2723

22 files changed

+911
-585
lines changed

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ services:
2121
ALCHEMY_KEY: ${ALCHEMY_KEY}
2222
TENDERLY_FORK_ID: ${TENDERLY_FORK_ID}
2323
TENDERLY_HEAD_ID: ${TENDERLY_HEAD_ID}
24+
DEFENDER_API_KEY: ${DEFENDER_API_KEY}
25+
DEFENDER_SECRET_KEY: ${DEFENDER_SECRET_KEY}

helpers/configuration.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
ICommonConfiguration,
77
eNetwork,
88
} from './types';
9-
import { getParamPerPool } from './contracts-helpers';
9+
import { getEthersSignersAddresses, getParamPerPool } from './contracts-helpers';
1010
import AaveConfig from '../markets/aave';
1111
import MaticConfig from '../markets/matic';
1212
import AmmConfig from '../markets/amm';
@@ -66,9 +66,7 @@ export const getGenesisPoolAdmin = async (
6666
if (targetAddress) {
6767
return targetAddress;
6868
}
69-
const addressList = await Promise.all(
70-
(await DRE.ethers.getSigners()).map((signer) => signer.getAddress())
71-
);
69+
const addressList = await getEthersSignersAddresses();
7270
const addressIndex = config.PoolAdminIndex;
7371
return addressList[addressIndex];
7472
};
@@ -81,9 +79,7 @@ export const getEmergencyAdmin = async (
8179
if (targetAddress) {
8280
return targetAddress;
8381
}
84-
const addressList = await Promise.all(
85-
(await DRE.ethers.getSigners()).map((signer) => signer.getAddress())
86-
);
82+
const addressList = await getEthersSignersAddresses();
8783
const addressIndex = config.EmergencyAdminIndex;
8884
return addressList[addressIndex];
8985
};

helpers/contracts-deployments.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolea
137137
linkedGenericLogicByteCode
138138
);
139139

140-
const genericLogic = await (await genericLogicFactory.deploy()).deployed();
140+
const genericLogic = await (
141+
await genericLogicFactory.connect(await getFirstSigner()).deploy()
142+
).deployed();
141143
return withSaveAndVerify(genericLogic, eContractid.GenericLogic, [], verify);
142144
};
143145

@@ -158,7 +160,9 @@ export const deployValidationLogic = async (
158160
linkedValidationLogicByteCode
159161
);
160162

161-
const validationLogic = await (await validationLogicFactory.deploy()).deployed();
163+
const validationLogic = await (
164+
await validationLogicFactory.connect(await getFirstSigner()).deploy()
165+
).deployed();
162166

163167
return withSaveAndVerify(validationLogic, eContractid.ValidationLogic, [], verify);
164168
};

helpers/contracts-getters.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ import {
3232
FlashLiquidationAdapterFactory,
3333
} from '../types';
3434
import { IERC20DetailedFactory } from '../types/IERC20DetailedFactory';
35-
import { MockTokenMap } from './contracts-helpers';
35+
import { getEthersSigners, MockTokenMap } from './contracts-helpers';
3636
import { DRE, getDb, notFalsyOrZeroAddress } from './misc-utils';
3737
import { eContractid, PoolConfiguration, tEthereumAddress, TokenContractId } from './types';
3838

39-
export const getFirstSigner = async () => (await DRE.ethers.getSigners())[0];
39+
export const getFirstSigner = async () => (await getEthersSigners())[0];
4040

4141
export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => {
4242
return await LendingPoolAddressesProviderFactory.connect(

helpers/contracts-helpers.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import { MintableERC20 } from '../types/MintableERC20';
2323
import { Artifact } from 'hardhat/types';
2424
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
2525
import { verifyEtherscanContract } from './etherscan-verification';
26-
import { getIErc20Detailed } from './contracts-getters';
26+
import { getFirstSigner, getIErc20Detailed } from './contracts-getters';
2727
import { usingTenderly, verifyAtTenderly } from './tenderly-utils';
2828
import { usingPolygon, verifyAtPolygon } from './polygon-utils';
29+
import { getDefenderRelaySigner, usingDefender } from './defender-utils';
2930

3031
export type MockTokenMap = { [symbol: string]: MintableERC20 };
3132

@@ -66,11 +67,18 @@ export const rawInsertContractAddressInDb = async (id: string, address: tEthereu
6667
})
6768
.write();
6869

69-
export const getEthersSigners = async (): Promise<Signer[]> =>
70-
await Promise.all(await DRE.ethers.getSigners());
70+
export const getEthersSigners = async (): Promise<Signer[]> => {
71+
const ethersSigners = await Promise.all(await DRE.ethers.getSigners());
72+
73+
if (usingDefender()) {
74+
const [, ...users] = ethersSigners;
75+
return [await getDefenderRelaySigner(), ...users];
76+
}
77+
return ethersSigners;
78+
};
7179

7280
export const getEthersSignersAddresses = async (): Promise<tEthereumAddress[]> =>
73-
await Promise.all((await DRE.ethers.getSigners()).map((signer) => signer.getAddress()));
81+
await Promise.all((await getEthersSigners()).map((signer) => signer.getAddress()));
7482

7583
export const getCurrentBlock = async () => {
7684
return DRE.ethers.provider.getBlockNumber();
@@ -83,9 +91,9 @@ export const deployContract = async <ContractType extends Contract>(
8391
contractName: string,
8492
args: any[]
8593
): Promise<ContractType> => {
86-
const contract = (await (await DRE.ethers.getContractFactory(contractName)).deploy(
87-
...args
88-
)) as ContractType;
94+
const contract = (await (await DRE.ethers.getContractFactory(contractName))
95+
.connect(await getFirstSigner())
96+
.deploy(...args)) as ContractType;
8997
await waitForTx(contract.deployTransaction);
9098
await registerContractInJsonDb(<eContractid>contractName, contract);
9199
return contract;

helpers/defender-utils.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { formatEther } from '@ethersproject/units';
2+
import { DefenderRelaySigner, DefenderRelayProvider } from 'defender-relay-client/lib/ethers';
3+
import { Signer } from 'ethers';
4+
import { HardhatRuntimeEnvironment } from 'hardhat/types';
5+
import { DRE, impersonateAccountsHardhat } from './misc-utils';
6+
import { usingTenderly } from './tenderly-utils';
7+
8+
export const usingDefender = () => process.env.DEFENDER === 'true';
9+
10+
export const getDefenderRelaySigner = async () => {
11+
const { DEFENDER_API_KEY, DEFENDER_SECRET_KEY } = process.env;
12+
let defenderSigner: Signer;
13+
14+
if (!DEFENDER_API_KEY || !DEFENDER_SECRET_KEY) {
15+
throw new Error('Defender secrets required');
16+
}
17+
18+
const credentials = { apiKey: DEFENDER_API_KEY, apiSecret: DEFENDER_SECRET_KEY };
19+
20+
defenderSigner = new DefenderRelaySigner(credentials, new DefenderRelayProvider(credentials), {
21+
speed: 'fast',
22+
});
23+
24+
const defenderAddress = await defenderSigner.getAddress();
25+
console.log(' - Using Defender Relay: ', defenderAddress);
26+
27+
// Replace signer if FORK=main is active
28+
if (process.env.FORK === 'main') {
29+
console.log(' - Impersonating Defender Relay');
30+
await impersonateAccountsHardhat([defenderAddress]);
31+
defenderSigner = await (DRE as HardhatRuntimeEnvironment).ethers.getSigner(defenderAddress);
32+
}
33+
// Replace signer if Tenderly network is active
34+
if (usingTenderly()) {
35+
console.log(' - Impersonating Defender Relay via Tenderly');
36+
defenderSigner = await (DRE as HardhatRuntimeEnvironment).ethers.getSigner(defenderAddress);
37+
}
38+
console.log(' - Balance: ', formatEther(await defenderSigner.getBalance()));
39+
40+
return defenderSigner;
41+
};

helpers/misc-utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,17 @@ export const notFalsyOrZeroAddress = (address: tEthereumAddress | null | undefin
115115
}
116116
return isAddress(address) && !isZeroAddress(address);
117117
};
118+
119+
export const impersonateAccountsHardhat = async (accounts: string[]) => {
120+
if (process.env.TENDERLY === 'true') {
121+
return;
122+
}
123+
// eslint-disable-next-line no-restricted-syntax
124+
for (const account of accounts) {
125+
// eslint-disable-next-line no-await-in-loop
126+
await (DRE as HardhatRuntimeEnvironment).network.provider.request({
127+
method: 'hardhat_impersonateAccount',
128+
params: [account],
129+
});
130+
}
131+
};

helpers/tenderly-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const usingTenderly = () =>
99

1010
export const verifyAtTenderly = async (id: string, instance: Contract) => {
1111
console.log('\n- Doing Tenderly contract verification of', id);
12-
await (DRE as any).tenderlyRPC.verify({
12+
await (DRE as any).tenderlyNetwork.verify({
1313
name: id,
1414
address: instance.address,
1515
});

0 commit comments

Comments
 (0)