-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
setup rpc tests and spell infra (#222)
* setup rpc tests and spell imfrastructure * fix rpc env * fix file names * fix typo * format * add new lp deployment to spell * fix typos
- Loading branch information
1 parent
b76a159
commit 2f07d31
Showing
4 changed files
with
281 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity 0.8.21; | ||
|
||
contract Addresses { | ||
address public root = address(0x498016d30Cd5f0db50d7ACE329C07313a0420502); | ||
address public investmentManager = address(0xbBF0AB988691dB1892ADaF7F0eF560Ca4c6DD73A); | ||
address public poolManager = address(0x78E9e622A57f70F1E0Ec652A4931E4e278e58142); | ||
address public gateway = address(0x634F036fE66579E901c7bA34e33DF422E37A0037); | ||
address public escrow = address(0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936); | ||
address public userEscrow= address(0x9fc3A3bcEdc1CaB14EfC1B7ef45dFBDd3d17c9d7); | ||
address public router = address(0x8174D5f12Ce682459864D8C081f9635012Ab51c2); | ||
address public trancheTokenFactory = address(0x4aEFE6CeFEd5D0A30679E41C0B3Fee6cbAa6ADf6); | ||
address public liquidityPoolFactory = address(0x77F48b2c942E6f3ac2232568d560e423c441386a); | ||
address public restrictionManagerFactory = address(0xf4D7F6919eF0B495a2551F7299324961F29aE7aC); | ||
address public pauseAdmin = address(0xce86472007Ea37a5d0208f8C1559A37530c8067C); | ||
address public delayedAdmin = address(0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028); | ||
address public messages = address(0xAf9F6Ac63C057EB7F59b6Fae2c3d447191b58Ea5); | ||
address public deployer = address(0x7270b20603FbB3dF0921381670fbd62b9991aDa4); | ||
address public admin = address(0xD9D30ab47c0f096b0AA67e9B8B1624504a63e7FD); // multisig | ||
|
||
// deployed LPs | ||
address public anemoyToken = address(0x30baA3BA9D7089fD8D020a994Db75D14CF7eC83b); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity 0.8.21; | ||
|
||
import "forge-std/Test.sol"; | ||
import {Addresses} from "deployments/ETH_MAINNET.sol"; | ||
import {Root} from "src/Root.sol"; | ||
import {InvestmentManager} from "src/InvestmentManager.sol"; | ||
import {PoolManager} from "src/PoolManager.sol"; | ||
import {Escrow} from "src/Escrow.sol"; | ||
import {UserEscrow} from "src/UserEscrow.sol"; | ||
import {TrancheToken} from "src/token/Tranche.sol"; | ||
import {Gateway} from "src/gateway/Gateway.sol"; | ||
import {AxelarRouter} from "src/gateway/routers/axelar/Router.sol"; | ||
import {TrancheTokenFactory, LiquidityPoolFactory, RestrictionManagerFactory} from "src/util/Factory.sol"; | ||
import {DelayedAdmin} from "src/admins/DelayedAdmin.sol"; | ||
import {PauseAdmin} from "src/admins/PauseAdmin.sol"; | ||
|
||
contract RPCTest is Test, Addresses { | ||
uint256 mainnetFork; | ||
string MAINNET_RPC_URL = vm.envString("MAINNET_RPC_URL"); | ||
|
||
function setUp() public virtual { | ||
mainnetFork = vm.createFork(MAINNET_RPC_URL); // setup ETH mainnet fork | ||
// use fork | ||
vm.selectFork(mainnetFork); | ||
} | ||
|
||
function testContractsWiredCorrectly() public { | ||
// investmentManager | ||
assertEq(address(InvestmentManager(investmentManager).escrow()), escrow); | ||
assertEq(address(InvestmentManager(investmentManager).userEscrow()), userEscrow); | ||
assertEq(address(InvestmentManager(investmentManager).gateway()), gateway); | ||
assertEq(address(InvestmentManager(investmentManager).poolManager()), poolManager); | ||
assertEq(address(Gateway(gateway).investmentManager()), investmentManager); | ||
assertEq(address(PoolManager(poolManager).investmentManager()), investmentManager); | ||
assertEq(InvestmentManager(investmentManager).wards(poolManager), 1); | ||
assertEq(Escrow(escrow).wards(investmentManager), 1); | ||
assertEq(UserEscrow(userEscrow).wards(investmentManager), 1); | ||
assertEq(InvestmentManager(investmentManager).wards(root), 1); | ||
assertEq(InvestmentManager(investmentManager).wards(deployer), 0); // deployer has no permissions | ||
|
||
// PoolManager | ||
assertEq(address(PoolManager(poolManager).gateway()), gateway); | ||
assertEq(address(PoolManager(poolManager).escrow()), escrow); | ||
assertEq(address(PoolManager(poolManager).investmentManager()), investmentManager); | ||
assertEq(address(PoolManager(poolManager).trancheTokenFactory()), trancheTokenFactory); | ||
assertEq(address(PoolManager(poolManager).liquidityPoolFactory()), liquidityPoolFactory); | ||
assertEq(address(PoolManager(poolManager).restrictionManagerFactory()), restrictionManagerFactory); | ||
assertEq(address(Gateway(gateway).poolManager()), poolManager); | ||
assertEq(address(InvestmentManager(investmentManager).poolManager()), poolManager); | ||
assertEq(InvestmentManager(investmentManager).wards(poolManager), 1); | ||
assertEq(Escrow(escrow).wards(poolManager), 1); | ||
assertEq(InvestmentManager(investmentManager).wards(poolManager), 1); | ||
assertEq(PoolManager(poolManager).wards(root), 1); | ||
assertEq(PoolManager(poolManager).wards(deployer), 0); // deployer has no permissions | ||
|
||
// Gateway | ||
assertEq(address(Gateway(gateway).investmentManager()), investmentManager); | ||
assertEq(address(Gateway(gateway).poolManager()), poolManager); | ||
assertEq(address(Gateway(gateway).root()), root); | ||
assertEq(address(InvestmentManager(investmentManager).gateway()), gateway); | ||
assertEq(address(PoolManager(poolManager).gateway()), gateway); | ||
assertEq(address(Gateway(gateway).outgoingRouter()), router); | ||
assertTrue(Gateway(gateway).incomingRouters(router)); | ||
assertEq(Gateway(gateway).wards(root), 1); | ||
assertEq(Root(root).wards(gateway), 1); | ||
assertEq(Gateway(gateway).wards(deployer), 0); // deployer has no permissions | ||
|
||
// Escrow | ||
assertEq(Escrow(escrow).wards(root), 1); | ||
assertEq(Escrow(escrow).wards(deployer), 0); // deployer has no permissions | ||
|
||
// UserEscrow | ||
assertEq(UserEscrow(userEscrow).wards(root), 1); | ||
assertEq(UserEscrow(userEscrow).wards(deployer), 0); // deployer has no permissions | ||
|
||
// router | ||
assertEq(AxelarRouter(router).wards(root), 1); | ||
assertEq(AxelarRouter(router).wards(deployer), 0); // deployer has no permissions | ||
|
||
// trancheTokenFactory | ||
assertEq(address(PoolManager(poolManager).trancheTokenFactory()), trancheTokenFactory); | ||
assertEq(TrancheTokenFactory(trancheTokenFactory).wards(root), 1); | ||
assertEq(TrancheTokenFactory(trancheTokenFactory).wards(deployer), 0); // deployer has no permissions | ||
|
||
// liquidityPoolFactory | ||
assertEq(address(PoolManager(poolManager).liquidityPoolFactory()), liquidityPoolFactory); | ||
assertEq(LiquidityPoolFactory(liquidityPoolFactory).root(), root); | ||
assertEq(LiquidityPoolFactory(liquidityPoolFactory).wards(root), 1); | ||
assertEq(LiquidityPoolFactory(liquidityPoolFactory).wards(poolManager), 1); | ||
assertEq(LiquidityPoolFactory(liquidityPoolFactory).wards(deployer), 0); // deployer has no permissions | ||
|
||
// restrictionMangerFactory | ||
assertEq(address(PoolManager(poolManager).restrictionManagerFactory()), restrictionManagerFactory); | ||
assertEq(RestrictionManagerFactory(restrictionManagerFactory).wards(root), 1); | ||
assertEq(RestrictionManagerFactory(restrictionManagerFactory).wards(deployer), 0); // deployer has no | ||
// permissions | ||
|
||
// delayedAdmin | ||
assertEq(address(DelayedAdmin(delayedAdmin).root()), root); | ||
assertEq(DelayedAdmin(delayedAdmin).wards(admin), 1); | ||
assertEq(Root(root).wards(delayedAdmin), 1); | ||
assertEq(DelayedAdmin(delayedAdmin).wards(root), 0); | ||
assertEq(DelayedAdmin(delayedAdmin).wards(deployer), 0); // deployer has no permissions | ||
|
||
// pauseAdmin | ||
assertEq(address(PauseAdmin(pauseAdmin).root()), root); | ||
assertEq(PauseAdmin(pauseAdmin).wards(delayedAdmin), 1); | ||
// assertEq(PauseAdmin(pauseAdmin).wards(admin), 0); // todo: add once spell executed | ||
assertEq(Root(root).wards(pauseAdmin), 1); | ||
assertEq(PauseAdmin(pauseAdmin).wards(root), 0); | ||
assertEq(PauseAdmin(pauseAdmin).wards(deployer), 0); // deployer has no permissions | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity 0.8.21; | ||
|
||
import "deployments/ETH_MAINNET.sol"; | ||
|
||
interface RootLike { | ||
function relyContract(address, address) external; | ||
} | ||
|
||
interface FileLike { | ||
function file(bytes32, address) external; | ||
} | ||
|
||
interface AuthLike { | ||
function rely(address) external; | ||
function deny(address) external; | ||
} | ||
|
||
interface PoolManagerLike { | ||
function removeLiquidityPool(uint64 poolId, bytes16 trancheId, address currency) external; | ||
function deployLiquidityPool(uint64 poolId, bytes16 trancheId, address currency) external returns (address); | ||
function getLiquidityPool(uint64 poolId, bytes16 trancheId, address currency) external returns (address); | ||
} | ||
|
||
interface LiquidityPoolLike { | ||
function poolId() external returns (uint64); | ||
function trancheId() external returns (bytes16); | ||
function asset() external returns (address); | ||
} | ||
|
||
// Spell to migrate the LiquidityPool factory contract | ||
contract Spell is Addresses { | ||
bool public done; | ||
string public constant description = "Liquidity Pool Factory migration spell"; | ||
|
||
address public constant LIQUIDITY_POOL_FACTORY_NEW = address(0x8273E36EEcf7A8604BEdEe68FC24Af121B64f165); | ||
address public constant DEPRECATED_LIQUIDITY_POOL = address(0xa0872E8D2975483b2Ab4Afcee729133D8666F6f5); | ||
address public newLiquidityPool; | ||
|
||
address self; | ||
|
||
function cast() public { | ||
require(!done, "spell-already-cast"); | ||
done = true; | ||
execute(); | ||
} | ||
|
||
function execute() internal { | ||
self = address(this); | ||
|
||
// give spell required permissions | ||
RootLike root = RootLike(root); | ||
root.relyContract(LIQUIDITY_POOL_FACTORY_NEW, self); | ||
root.relyContract(poolManager, self); | ||
|
||
// spell magic | ||
migrateLiquidityPoolFactory(); | ||
migrateLiquidityPool(); | ||
|
||
// revoke all permissions from spell | ||
AuthLike(address(root)).deny(self); | ||
AuthLike(LIQUIDITY_POOL_FACTORY_NEW).deny(self); | ||
AuthLike(poolManager).deny(self); | ||
} | ||
|
||
function migrateLiquidityPoolFactory() internal { | ||
AuthLike(LIQUIDITY_POOL_FACTORY_NEW).rely(poolManager); | ||
AuthLike(LIQUIDITY_POOL_FACTORY_NEW).deny(deployer); | ||
FileLike(poolManager).file("liquidityPoolFactory", LIQUIDITY_POOL_FACTORY_NEW); | ||
} | ||
|
||
function migrateLiquidityPool() internal { | ||
LiquidityPoolLike deprectaedLP = LiquidityPoolLike(DEPRECATED_LIQUIDITY_POOL); | ||
address deprectaedLP_ = PoolManagerLike(poolManager).getLiquidityPool( | ||
deprectaedLP.poolId(), deprectaedLP.trancheId(), deprectaedLP.asset() | ||
); | ||
require(deprectaedLP_ == DEPRECATED_LIQUIDITY_POOL, "SPELL - unknown Liquidity Pool"); | ||
// remove deprectaed pool | ||
PoolManagerLike(poolManager).removeLiquidityPool( | ||
deprectaedLP.poolId(), deprectaedLP.trancheId(), deprectaedLP.asset() | ||
); | ||
// add new pool | ||
newLiquidityPool = PoolManagerLike(poolManager).deployLiquidityPool( | ||
deprectaedLP.poolId(), deprectaedLP.trancheId(), deprectaedLP.asset() | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity 0.8.21; | ||
|
||
import "../rpc/RPC.t.sol"; | ||
import "./Spell.sol"; | ||
|
||
contract SpellTest is RPCTest { | ||
Spell spell; | ||
|
||
function setUp() public override { | ||
super.setUp(); | ||
spell = new Spell(); | ||
|
||
address newLPFactory = spell.LIQUIDITY_POOL_FACTORY_NEW(); | ||
|
||
// rely root on new factory -> to be done manually before spell cast | ||
vm.prank(deployer); | ||
AuthLike(newLPFactory).rely(root); | ||
|
||
liquidityPoolFactory = newLPFactory; // replace liquidityPoolFactory address in the deployment addresses to | ||
// check for correct wiring | ||
castSpell(); | ||
} | ||
|
||
function castSpell() public { | ||
// admin submits a tx to delayedAdmin in order to rely spell -> to be done manually before spell cast | ||
vm.prank(admin); | ||
DelayedAdmin(delayedAdmin).scheduleRely(address(spell)); | ||
// warp to the time when the spell can be cast -> current block + delay | ||
vm.warp(block.timestamp + Root(root).delay()); | ||
Root(root).executeScheduledRely(address(spell)); // --> to be called after delay has passed | ||
spell.cast(); | ||
} | ||
|
||
function testCastSuccessful() public { | ||
address newLP_ = spell.newLiquidityPool(); | ||
address deprecatedLP_ = spell.DEPRECATED_LIQUIDITY_POOL(); | ||
LiquidityPoolLike deprecatedLP = LiquidityPoolLike(deprecatedLP_); | ||
LiquidityPoolLike newLP = LiquidityPoolLike(newLP_); | ||
|
||
assertEq(deprecatedLP.poolId(), newLP.poolId()); | ||
assertEq(deprecatedLP.trancheId(), newLP.trancheId()); | ||
assertEq(deprecatedLP.asset(), newLP.asset()); | ||
|
||
// check if deprectaed pool removed correctly | ||
assertEq(InvestmentManager(investmentManager).wards(deprecatedLP_), 0); | ||
assertEq(TrancheToken(anemoyToken).wards(deprecatedLP_), 0); | ||
assertEq(TrancheToken(anemoyToken).isTrustedForwarder(deprecatedLP_), false); | ||
assertEq(TrancheToken(anemoyToken).allowance(address(escrow), deprecatedLP_), 0); | ||
|
||
// check if new pool added correctly | ||
assertEq(InvestmentManager(investmentManager).wards(newLP_), 1); | ||
assertEq(TrancheToken(anemoyToken).wards(newLP_), 1); | ||
assertEq(TrancheToken(anemoyToken).isTrustedForwarder(newLP_), true); | ||
assertEq(TrancheToken(anemoyToken).allowance(address(escrow), newLP_), UINT256_MAX); | ||
} | ||
} |