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

Create recovery helper deployment #2033

Merged
merged 3 commits into from
Nov 22, 2022
Merged
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
1 change: 1 addition & 0 deletions pkg/deployments/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Deployed core Pool factories (`WeightedPoolFactory`, `ComposableStablePoolFactory`, `LiquidityBootstrappingPool`, `AaveLinearPool`) to BNB.
- Deployed `AuthorizerAdaptorEntrypoint` to all networks.
- Deployed `AaveLinearPoolFactory` to all networks.
- Deployed `PoolRecoveryHelper` to all networks.

## 3.0.0 (2022-10-25)

Expand Down
1 change: 1 addition & 0 deletions pkg/deployments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Returns an object with all contracts from a deployment and their addresses.
| Protocol Fee Splitter | [`20221027-fee-splitter`](./tasks/20221027-fee-splitter) |
| Authorizer Adaptor Entrypoint | [`20221111-authorizer-adaptor-entrypoint`](./tasks/20221111-authorizer-adaptor-entrypoint) |
| Linear Pools for Aave aTokens with built-in rebalancing | [`20221115-aave-rebalanced-linear-pool`](./tasks/20221115-aave-rebalanced-linear-pool) |
| Pool Recovery Helper | [`20221123-pool-recovery-helper`](./tasks/20221123-pool-recovery-helper) |

## Scripts

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
[
{
"inputs": [
{
"internalType": "contract IVault",
"name": "vault",
"type": "address"
},
{
"internalType": "address[]",
"name": "initialFactories",
"type": "address[]"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "factory",
"type": "address"
}
],
"name": "addPoolFactory",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "enableRecoveryMode",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "selector",
"type": "bytes4"
}
],
"name": "getActionId",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getAuthorizer",
"outputs": [
{
"internalType": "contract IAuthorizer",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "getFactoryAtIndex",
"outputs": [
{
"internalType": "contract IBasePoolFactory",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getFactoryCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getVault",
"outputs": [
{
"internalType": "contract IVault",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "isPoolFromKnownFactory",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "factory",
"type": "address"
}
],
"name": "removePoolFactory",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"creationCode": "60c06040523480156200001157600080fd5b506040516200112e3803806200112e833981016040819052620000349162000157565b306080526001600160601b0319606083901b1660a05260005b8151811015620000b757620000868282815181106200006857fe5b60200260200101516000620000c060201b620006981790919060201c565b620000ae5760405162461bcd60e51b8152600401620000a59062000225565b60405180910390fd5b6001016200004d565b5050506200029c565b6000620000ce838362000129565b6200011f57508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b0386169081179091558554908252828601909352604090209190915562000123565b5060005b92915050565b6001600160a01b031660009081526001919091016020526040902054151590565b8051620001238162000283565b600080604083850312156200016a578182fd5b8251620001778162000283565b602084810151919350906001600160401b038082111562000196578384fd5b818601915086601f830112620001aa578384fd5b815181811115620001b9578485fd5b8381029150620001cb8483016200025c565b8181528481019084860184860187018b1015620001e6578788fd5b8795505b838610156200021457620001ff8b826200014a565b835260019590950194918601918601620001ea565b508096505050505050509250929050565b60208082526019908201527f4475706c696361746520696e697469616c20666163746f727900000000000000604082015260600190565b6040518181016001600160401b03811182821017156200027b57600080fd5b604052919050565b6001600160a01b03811681146200029957600080fd5b50565b60805160a05160601c610e6b620002c3600039806102fe5250806102ae5250610e6b6000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a587bbe111610076578063d10474341161005b578063d104743414610136578063dc3f574e1461013e578063dc867b7914610151576100a3565b8063a587bbe11461011b578063aaabadc51461012e576100a3565b806326e54479146100a85780633a987dfa146100bd578063851c1bb3146100e65780638d928af814610106575b600080fd5b6100bb6100b6366004610ae6565b610164565b005b6100d06100cb366004610ae6565b6101b9565b6040516100dd9190610caa565b60405180910390f35b6100f96100f4366004610bcd565b6102aa565b6040516100dd9190610cb5565b61010e6102fc565b6040516100dd9190610c89565b61010e610129366004610c29565b610320565b61010e610332565b6100f96103be565b6100bb61014c366004610ae6565b6103ca565b6100bb61015f366004610ae6565b61064f565b61016c610721565b610177600082610767565b6101b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ad90610d21565b60405180910390fd5b50565b6000806101c66000610915565b905060005b8181101561029e5760006101df8183610919565b6040517f6634b75300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690636634b75390610234908890600401610c89565b60206040518083038186803b15801561024c57600080fd5b505afa158015610260573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102849190610bad565b1561029557600193505050506102a5565b506001016101cb565b5060009150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000826040516020016102df929190610c59565b604051602081830303815290604052805190602001209050919050565b7f000000000000000000000000000000000000000000000000000000000000000090565b600061032c8183610953565b92915050565b600061033c6102fc565b73ffffffffffffffffffffffffffffffffffffffff1663aaabadc56040518163ffffffff1660e01b815260040160206040518083038186803b15801561038157600080fd5b505afa158015610395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b99190610c0d565b905090565b60006103b96000610915565b6103d3816101b9565b610409576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ad90610cea565b60608173ffffffffffffffffffffffffffffffffffffffff1663238a2d596040518163ffffffff1660e01b815260040160006040518083038186803b15801561045157600080fd5b505afa158015610465573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104ab9190810190610b02565b905060005b815181101561061c57600073ffffffffffffffffffffffffffffffffffffffff168282815181106104dd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16146106145781818151811061050c57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663679aefce6040518163ffffffff1660e01b815260040160206040518083038186803b15801561055957600080fd5b505afa9250505080156105a7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105a491810190610c41565b60015b610612578273ffffffffffffffffffffffffffffffffffffffff166354a844ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105f357600080fd5b505af1158015610607573d6000803e3d6000fd5b5050505050506101b6565b505b6001016104b0565b506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ad90610d8f565b610657610721565b610662600082610698565b6101b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ad90610d58565b60006106a48383610976565b61071857508154600180820184556000848152602080822090930180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091558554908252828601909352604090209190915561032c565b50600092915050565b60006107506000357fffffffff00000000000000000000000000000000000000000000000000000000166102aa565b90506101b661075f82336109a4565b610191610a3a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054801561090b5783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80830191018082146108705760008660000182815481106107d557fe5b600091825260209091200154875473ffffffffffffffffffffffffffffffffffffffff9091169150819088908590811061080b57fe5b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff94851617905592909116815260018881019092526040902090830190555b855486908061087b57fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff8716825260018881019091526040822091909155935061032c92505050565b600091505061032c565b5490565b600082600001828154811061092a57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169392505050565b81546000906109659083106064610a3a565b61096f8383610919565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001919091016020526040902054151590565b60006109ae610332565b73ffffffffffffffffffffffffffffffffffffffff16639be2a8848484306040518463ffffffff1660e01b81526004016109ea93929190610cbe565b60206040518083038186803b158015610a0257600080fd5b505afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096f9190610bad565b81610a4857610a4881610a4c565b5050565b7f08c379a000000000000000000000000000000000000000000000000000000000600090815260206004526007602452600a808304818106603090810160081b83860601918390049283060160101b016642414c230000300160c81b6044526101b6917f42414c0000000000000000000000000000000000000000000000000000000000906242414c90606490fd5b805161032c81610e13565b600060208284031215610af7578081fd5b813561096f81610e13565b60006020808385031215610b14578182fd5b825167ffffffffffffffff80821115610b2b578384fd5b818501915085601f830112610b3e578384fd5b815181811115610b4c578485fd5b8381029150610b5c848301610dec565b8181528481019084860184860187018a1015610b76578788fd5b8795505b83861015610ba057610b8c8a82610adb565b835260019590950194918601918601610b7a565b5098975050505050505050565b600060208284031215610bbe578081fd5b8151801515811461096f578182fd5b600060208284031215610bde578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461096f578182fd5b600060208284031215610c1e578081fd5b815161096f81610e13565b600060208284031215610c3a578081fd5b5035919050565b600060208284031215610c52578081fd5b5051919050565b9182527fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b901515815260200190565b90815260200190565b92835273ffffffffffffffffffffffffffffffffffffffff918216602084015216604082015260600190565b6020808252601e908201527f506f6f6c206973206e6f742066726f6d206b6e6f776e20666163746f72790000604082015260600190565b60208082526014908201527f4e6f6e2d6578697374656e7420666163746f7279000000000000000000000000604082015260600190565b60208082526011908201527f4475706c696361746520666163746f7279000000000000000000000000000000604082015260600190565b60208082526023908201527f506f6f6c277320726174652070726f76696465727320646f206e6f742072657660408201527f6572740000000000000000000000000000000000000000000000000000000000606082015260800190565b60405181810167ffffffffffffffff81118282101715610e0b57600080fd5b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146101b657600080fdfea26469706673582212204a4ddb678100ac3d28b3cc7a63dd5c7ebd98961521f276072a8d3a453b9caa8564736f6c63430007010033"
}
10 changes: 10 additions & 0 deletions pkg/deployments/tasks/20221123-pool-recovery-helper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Task from '../../src/task';
import { TaskRunOptions } from '../../src/types';
import { PoolRecoveryHelperDeployment } from './input';

export default async (task: Task, { force, from }: TaskRunOptions = {}): Promise<void> => {
const input = task.input() as PoolRecoveryHelperDeployment;

const args = [input.Vault, input.InitialFactories];
await task.deployAndVerify('PoolRecoveryHelper', args, from, force);
};
50 changes: 50 additions & 0 deletions pkg/deployments/tasks/20221123-pool-recovery-helper/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Task, { TaskMode } from '../../src/task';

export type PoolRecoveryHelperDeployment = {
Vault: string;
InitialFactories: Array<string>;
};

const Vault = new Task('20210418-vault', TaskMode.READ_ONLY);
const ComposableStablePoolFactoryTask = new Task('20220906-composable-stable-pool', TaskMode.READ_ONLY);
const WeightedPoolFactoryTask = new Task('20220908-weighted-pool-v2', TaskMode.READ_ONLY);

export default {
Vault,
mainnet: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'mainnet' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'mainnet' }).WeightedPoolFactory,
],
},
goerli: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'goerli' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'goerli' }).WeightedPoolFactory,
],
},
polygon: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'polygon' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'polygon' }).WeightedPoolFactory,
],
},
arbitrum: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'arbitrum' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'arbitrum' }).WeightedPoolFactory,
],
},
optimism: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'optimism' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'optimism' }).WeightedPoolFactory,
],
},
bsc: {
InitialFactories: [
ComposableStablePoolFactoryTask.output({ network: 'bsc' }).ComposableStablePoolFactory,
WeightedPoolFactoryTask.output({ network: 'bsc' }).WeightedPoolFactory,
],
},
};
13 changes: 13 additions & 0 deletions pkg/deployments/tasks/20221123-pool-recovery-helper/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 2022-11-22 - Pool Recovery Helper

Deployment of the `PoolRecoveryHelper`, which allows creating Managed Pools.

## Useful Files

- [Ethereum addresses](./output/mainnet.json)
- [Polygon addresses](./output/polygon.json)
- [Arbitrum addresses](./output/arbitrum.json)
- [Optimism addresses](./output/optimism.json)
- [Binance addresses](./output/bsc.json)
- [Gnosis addresses](./output/gnosis.json)
- [`PoolRecoveryHelper` ABI](./abi/PoolRecoveryHelper.json)
102 changes: 102 additions & 0 deletions pkg/deployments/tasks/20221123-pool-recovery-helper/test/test.fork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import hre from 'hardhat';
import { expect } from 'chai';
import { Contract } from 'ethers';

import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { actionId } from '@balancer-labs/v2-helpers/src/models/misc/actions';
import { ZERO_ADDRESS } from '@balancer-labs/v2-helpers/src/constants';

import { describeForkTest, impersonate, getForkedNetwork, Task, TaskMode, getSigner } from '../../../src';
import { setCode } from '@nomicfoundation/hardhat-network-helpers';

describeForkTest('PoolRecoveryHelper', 'mainnet', 15998800, function () {
let task: Task;

let helper: Contract;
let operator: SignerWithAddress, admin: SignerWithAddress;
let vault: Contract, authorizer: Contract;

const POOL_STABLE = '0xbD482fFb3E6E50dC1c437557C3Bea2B68f3683Ee'; // From ComposableStablePoolFactory
const POOL_WEIGHTED = '0xe340EBfcAA544da8bB1Ee9005F1a346D50Ec422e'; // From WeightedPoolFactory

before('run task', async () => {
task = new Task('20221123-pool-recovery-helper', TaskMode.TEST, getForkedNetwork(hre));
await task.run({ force: true });
helper = await task.deployedInstance('PoolRecoveryHelper');
});

before('load vault', async () => {
const vaultTask = new Task('20210418-vault', TaskMode.READ_ONLY, getForkedNetwork(hre));
vault = await vaultTask.deployedInstance('Vault');

const authorizerTask = new Task('20210418-authorizer', TaskMode.READ_ONLY, getForkedNetwork(hre));
authorizer = await authorizerTask.deployedInstance('Authorizer');
});

before('load signers', async () => {
// We impersonate an account with the default admin role in order to be able to grant permissions. This assumes
// such an account exists.
admin = await impersonate(await authorizer.getRoleMember(await authorizer.DEFAULT_ADMIN_ROLE(), 0));
operator = await getSigner();
});

before('approve helper at the authorizer', async () => {
const selector = task.artifact('IRecoveryMode').evm.methodIdentifiers['enableRecoveryMode()'];

const actionIds = await Promise.all(
[POOL_STABLE, POOL_WEIGHTED].map(async (poolAddress) => {
const pool = await task.instanceAt('IAuthentication', poolAddress);
return await pool.getActionId(`0x${selector}`);
})
);

// Grant helper permission to enable recovery mode
await authorizer.connect(admin).grantRoles(actionIds, helper.address);
});

before('approve operator at the authorizer', async () => {
const actionIds = await Promise.all(
['addPoolFactory', 'removePoolFactory'].map(async (method) => actionId(helper, method))
);
await authorizer.connect(admin).grantRoles(actionIds, operator.address);
});
context('with ComposableStablePool', () => {
itWorksWithPool(POOL_STABLE);
});

context('with WeightedPool', () => {
itWorksWithPool(POOL_WEIGHTED);
});

function itWorksWithPool(poolAddress: string) {
it('recognizes pools from the initial factories', async () => {
expect(await helper.isPoolFromKnownFactory(poolAddress)).to.equal(true);
});

it("reverts if the pool rate providers don't revert", async () => {
await expect(helper.enableRecoveryMode(poolAddress)).to.be.revertedWith("Pool's rate providers do not revert");
});

it('puts the pool in recovery mode if one of the rate providers reverts', async () => {
// We get the first non-zero rate provider of the Pool, and replace it with a mock one that reverts
const rateProviderPool = await task.instanceAt('IRateProviderPool', poolAddress);
const rateProviders = await rateProviderPool.getRateProviders();
const mockedRateProvider: string = rateProviders.filter((provider) => provider !== ZERO_ADDRESS)[0];

// Make sure there's at least one rate provider
expect(mockedRateProvider).to.not.equal(undefined);

await setCode(
mockedRateProvider,
`0x${(await task.artifact('MockRevertingRateProvider')).evm.deployedBytecode.object}`
);
const mockLendingPool = await task.instanceAt('MockRevertingRateProvider', mockedRateProvider);
await mockLendingPool.setRevertOnGetRate(true);

await helper.enableRecoveryMode(poolAddress);

const recoveryModePool = await task.instanceAt('IRecoveryMode', poolAddress);
expect(await recoveryModePool.inRecoveryMode()).to.equal(true);
});
}
});