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

Migration spell #385

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
17dd13c
add simulation for tranche token migration
ilinzweilin Jul 12, 2024
8dfcbf2
add comments
ilinzweilin Jul 12, 2024
b88e336
Merge remote-tracking branch 'origin' into tranche-token-migration-fo…
ilinzweilin Jul 12, 2024
5f15f10
Merge branch 'main' into tranche-token-migration-fork-test
ilinzweilin Jul 29, 2024
a23c86c
add migration spell
ilinzweilin Jul 29, 2024
ac67490
add migration spell
ilinzweilin Jul 29, 2024
c88ff07
Merge branch 'main' into migration-spell
AStox Jul 30, 2024
f0e4945
migrate all members to new memberlist and claim any unclaimed tokens
AStox Jul 30, 2024
1c2bbbb
Add denies
AStox Jul 30, 2024
b809f8b
fix build
AStox Jul 30, 2024
1922321
update fork test
AStox Jul 31, 2024
77f62b1
upgrade fork test, fix a missing rely and use maxMint instead of escr…
AStox Jul 31, 2024
0f8e790
wip: add test for fork testing against a real deployment
AStox Jul 31, 2024
2bb0914
Add base addresses
AStox Aug 1, 2024
e6c00e3
update tests and spells construction
AStox Aug 1, 2024
1e310d3
forge fmt
AStox Aug 1, 2024
c63127a
Merge branch 'main' into migration-spell
AStox Aug 1, 2024
5548e5b
derive some addresses via the old vault
AStox Aug 1, 2024
05498a2
add new deployments
AStox Aug 1, 2024
3b202f3
derive currency id, update token names, use approximate asserts
AStox Aug 1, 2024
b283ca5
update NS3SR old share metadata
AStox Aug 1, 2024
b359596
break spell into two executable parts
AStox Aug 1, 2024
c127965
update tests to cast both parts seperately
AStox Aug 1, 2024
e030960
update tests to test all spells at once
AStox Aug 1, 2024
6d5636c
get the allEVMSpells test working
AStox Aug 1, 2024
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
2 changes: 1 addition & 1 deletion deployments/mainnet/ethereum-mainnet.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"chainId": 1,
"rpcUrl": "https://mainnet.infura.io/v3/ed5e0e19bcbc427cbf8f661736d44516",
"rpcUrl": "https://mainnet.infura.io/v3/e5a02bbddefe47f88c2d087ec4a37744",
"config": {
"commitHash": "da5c31462b5fe615d3510ca35f884018fd8055c7",
"deployer": "0x7270b20603FbB3dF0921381670fbd62b9991aDa4",
Expand Down
2 changes: 1 addition & 1 deletion script/Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import "forge-std/Script.sol";

contract Deployer is Script {
uint256 internal constant delay = 48 hours;
address adminSafe;
address adminSafe = 0xD9D30ab47c0f096b0AA67e9B8B1624504a63e7FD; // safe wallet for fork testing
address[] adapters;

Root public root;
Expand Down
128 changes: 128 additions & 0 deletions src/spell/MigrationSpellBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;

import {IRoot} from "src/interfaces/IRoot.sol";
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
import {RestrictionUpdate} from "src/interfaces/token/IRestrictionManager.sol";
import {ITranche} from "src/interfaces/token/ITranche.sol";
import {IInvestmentManager} from "src/interfaces/IInvestmentManager.sol";
import {CastLib} from "src/libraries/CastLib.sol";
import {IAuth} from "src/interfaces/IAuth.sol";

interface ITrancheOld {
function authTransferFrom(address from, address to, uint256 value) external returns (bool);
}

interface IVaultOld {
function poolId() external view returns (uint64);
function trancheId() external view returns (bytes16);
function share() external view returns (address);
function manager() external view returns (address);
function escrow() external view returns (address);
function asset() external view returns (address);
}

contract MigrationSpellBase {
using CastLib for *;

string public NETWORK;
uint128 public CURRENCY_ID;
address public ROOT_OLD;
address public ADMIN_MULTISIG;
address public GUARDIAN_OLD;
address public VAULT_OLD;
address public ROOT_NEW;
address public GUARDIAN_NEW;
address public POOLMANAGER_NEW;
address public RESTRICTIONMANAGER_NEW;
ITranche public trancheTokenNew;
string public NAME;
string public SYMBOL;
string public NAME_OLD;
string public SYMBOL_OLD;
address[] public memberlistMembers;
mapping(address => uint64) public validUntil;
bool public done;
uint256 constant ONE = 10 ** 27;
address self;

function cast() public {
require(!done, "spell-already-cast");
done = true;
execute();
}

function execute() internal {
self = address(this);
IRoot rootOld = IRoot(address(ROOT_OLD));
IRoot rootNew = IRoot(address(ROOT_NEW));
IVaultOld vaultOld = IVaultOld(VAULT_OLD);
uint64 POOL_ID = vaultOld.poolId();
bytes16 TRANCHE_ID = vaultOld.trancheId();
IPoolManager poolManager = IPoolManager(address(POOLMANAGER_NEW));
ITranche trancheTokenOld = ITranche(vaultOld.share());
uint8 DECIMALS = trancheTokenOld.decimals();
IInvestmentManager investmentManagerOld = IInvestmentManager(vaultOld.manager());
rootOld.relyContract(address(investmentManagerOld), self);
rootOld.relyContract(address(trancheTokenOld), self);

// deploy new tranche token
rootNew.relyContract(address(POOLMANAGER_NEW), self);
poolManager.addPool(POOL_ID);
poolManager.addTranche(POOL_ID, TRANCHE_ID, NAME, SYMBOL, DECIMALS, RESTRICTIONMANAGER_NEW);
poolManager.addAsset(CURRENCY_ID, vaultOld.asset());
poolManager.allowAsset(POOL_ID, CURRENCY_ID);
trancheTokenNew = ITranche(poolManager.deployTranche(POOL_ID, TRANCHE_ID));
rootNew.relyContract(address(trancheTokenNew), self);

// add all old members to new memberlist and claim any tokens
uint256 holderBalance;
for (uint8 i; i < memberlistMembers.length; i++) {
// add member to new memberlist
poolManager.updateRestriction(
POOL_ID,
TRANCHE_ID,
abi.encodePacked(
uint8(RestrictionUpdate.UpdateMember),
address(memberlistMembers[i]).toBytes32(),
validUntil[memberlistMembers[i]]
)
);
if (memberlistMembers[i] != vaultOld.escrow()) {
uint256 maxMint = investmentManagerOld.maxMint(VAULT_OLD, memberlistMembers[i]);
if (maxMint > 0) {
// Claim any unclaimed tokens the user may have
investmentManagerOld.mint(VAULT_OLD, maxMint, memberlistMembers[i], memberlistMembers[i]);
}
holderBalance = trancheTokenOld.balanceOf(memberlistMembers[i]);
if (holderBalance > 0) {
// mint new token to the holder's wallet
trancheTokenNew.mint(memberlistMembers[i], holderBalance);
// transfer old tokens from holders' wallets
ITrancheOld(vaultOld.share()).authTransferFrom(memberlistMembers[i], self, holderBalance);
}
}
}

// burn entire supply of old tranche tokens
trancheTokenOld.burn(self, trancheTokenOld.balanceOf(self));

// rename old tranche token
trancheTokenOld.file("name", NAME_OLD);
trancheTokenOld.file("symbol", SYMBOL_OLD);

// denies
rootNew.denyContract(address(POOLMANAGER_NEW), self);
rootNew.denyContract(address(trancheTokenNew), self);
rootOld.denyContract(address(trancheTokenOld), self);
rootOld.denyContract(address(investmentManagerOld), self);
IAuth(address(rootOld)).deny(self);
IAuth(address(rootNew)).deny(self);

poolManager.deployVault(POOL_ID, TRANCHE_ID, vaultOld.asset());
}

function getNumberOfMigratedMembers() public view returns (uint256) {
return memberlistMembers.length;
}
}
44 changes: 44 additions & 0 deletions src/spell/ShareMigration_DYF_EVM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pragma solidity 0.8.26;

import {IRoot} from "src/interfaces/IRoot.sol";
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
import {RestrictionUpdate} from "src/interfaces/token/IRestrictionManager.sol";
import {ITranche} from "src/interfaces/token/ITranche.sol";
import {IInvestmentManager} from "src/interfaces/IInvestmentManager.sol";
import {IAuth} from "src/interfaces/IAuth.sol";
import {MigrationSpellBase} from "src/spell/MigrationSpellBase.sol";

interface ITrancheOld {
function authTransferFrom(address from, address to, uint256 value) external returns (bool);
}

// spell to migrate tranche tokens
contract MigrationSpell is MigrationSpellBase {
constructor() {
NETWORK = "ethereum-mainnet";
// old deployment addresses
CURRENCY_ID = 242333941209166991950178742833476896417;
ROOT_OLD = 0x498016d30Cd5f0db50d7ACE329C07313a0420502;
ADMIN_MULTISIG = 0xD9D30ab47c0f096b0AA67e9B8B1624504a63e7FD;
GUARDIAN_OLD = 0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028;

// old pool addresses
VAULT_OLD = 0x110379504D933BeD2E485E281bc3909D1E7C9E5D;

// new deployment addresses
ROOT_NEW = 0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC;
GUARDIAN_NEW = 0x09ab10a9c3E6Eac1d18270a2322B6113F4C7f5E8;
POOLMANAGER_NEW = 0x91808B5E2F6d7483D41A681034D7c9DbB64B9E29;
RESTRICTIONMANAGER_NEW = 0x4737C3f62Cc265e786b280153fC666cEA2fBc0c0;

// information to deploy the new tranche token & liquidity pool to be able to migrate the tokens
NAME = "Anemoy DeFi Yield Fund 1 SP DeFi Yield Fund Token";
hieronx marked this conversation as resolved.
Show resolved Hide resolved
SYMBOL = "DYF";
NAME_OLD = "DEPRECATED";
SYMBOL_OLD = "DEPRECATED";

memberlistMembers = [0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936, 0x30d3bbAE8623d0e9C0db5c27B82dCDA39De40997];
validUntil[0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936] = type(uint64).max;
validUntil[0x30d3bbAE8623d0e9C0db5c27B82dCDA39De40997] = 2032178598;
}
}
44 changes: 44 additions & 0 deletions src/spell/ShareMigration_LTF_Base.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pragma solidity 0.8.26;

import {MigrationSpellBase} from "src/spell/MigrationSpellBase.sol";

interface ITrancheOld {
function authTransferFrom(address from, address to, uint256 value) external returns (bool);
}

contract MigrationSpell is MigrationSpellBase {
constructor() {
NETWORK = "base-mainnet";
// old deployment addresses
CURRENCY_ID = 242333941209166991950178742833476896418;
ROOT_OLD = 0x498016d30Cd5f0db50d7ACE329C07313a0420502;
ADMIN_MULTISIG = 0x8b83962fB9dB346a20c95D98d4E312f17f4C0d9b;
GUARDIAN_OLD = 0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028;

// old pool addresses
VAULT_OLD = 0xa0872E8D2975483b2Ab4Afcee729133D8666F6f5;

// new deployment addresses
ROOT_NEW = 0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC;
GUARDIAN_NEW = 0x427A1ce127b1775e4Cbd4F58ad468B9F832eA7e9;
POOLMANAGER_NEW = 0x7f192F34499DdB2bE06c4754CFf2a21c4B056994;
RESTRICTIONMANAGER_NEW = 0x4737C3f62Cc265e786b280153fC666cEA2fBc0c0;

// information to deploy the new tranche token & liquidity pool to be able to migrate the tokens
NAME = "Anemoy Liquid Treasury Fund 1";
SYMBOL = "LTF";

NAME_OLD = "DEPRECATED";
SYMBOL_OLD = "DEPRECATED";

memberlistMembers = [
0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936,
0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb,
0x86552B8d4F4a600D92d516eE8eA8B922EFEcB561
];

validUntil[0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936] = type(uint64).max;
validUntil[0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb] = 2035284942;
validUntil[0x86552B8d4F4a600D92d516eE8eA8B922EFEcB561] = 2037188297;
}
}
44 changes: 44 additions & 0 deletions src/spell/ShareMigration_LTF_Celo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pragma solidity 0.8.26;

import {MigrationSpellBase} from "src/spell/MigrationSpellBase.sol";

interface ITrancheOld {
function authTransferFrom(address from, address to, uint256 value) external returns (bool);
}

contract MigrationSpell is MigrationSpellBase {
constructor() {
NETWORK = "celo-mainnet";
// old deployment addresses
CURRENCY_ID = 242333941209166991950178742833476896420;
ROOT_OLD = 0x498016d30Cd5f0db50d7ACE329C07313a0420502;
ADMIN_MULTISIG = 0x2464f95F6901233bF4a0130A3611d5B4CBd83195;
GUARDIAN_OLD = 0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028;

// old pool addresses
VAULT_OLD = 0xa0872E8D2975483b2Ab4Afcee729133D8666F6f5;

// new deployment addresses
ROOT_NEW = 0x89e0E9ef81966BfA7D64BBE76394D36014a685c3;
GUARDIAN_NEW = 0x32043A41F4be198C4f6590312F7A7b91624Cab57;
POOLMANAGER_NEW = 0xa3Ce97352C1469884EEF3547Ec9362329FE78Cf0;
RESTRICTIONMANAGER_NEW = 0x9d5fbC48077863d63a883f44F66aCCde72A9D4e2;

// information to deploy the new tranche token & liquidity pool to be able to migrate the tokens
NAME = "Anemoy Liquid Treasury Fund 1";
SYMBOL = "LTF";

NAME_OLD = "DEPRECATED";
SYMBOL_OLD = "DEPRECATED";

memberlistMembers = [
0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936,
0x0D9E269ECc319BAE886Dd8c8B98F7B89269C2B1B,
0x6854f6671c1934c77cf7592B0b264f762614014E
];

validUntil[0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936] = type(uint64).max;
validUntil[0x0D9E269ECc319BAE886Dd8c8B98F7B89269C2B1B] = 2020186137;
validUntil[0x6854f6671c1934c77cf7592B0b264f762614014E] = 2020262249;
}
}
49 changes: 49 additions & 0 deletions src/spell/ShareMigration_LTF_EVM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
pragma solidity 0.8.26;

import {MigrationSpellBase} from "src/spell/MigrationSpellBase.sol";

// spell to migrate tranche tokens
contract MigrationSpell is MigrationSpellBase {
constructor() {
NETWORK = "ethereum-mainnet";
// old deployment addresses
CURRENCY_ID = 242333941209166991950178742833476896417;
hieronx marked this conversation as resolved.
Show resolved Hide resolved
ROOT_OLD = 0x498016d30Cd5f0db50d7ACE329C07313a0420502;
ADMIN_MULTISIG = 0xD9D30ab47c0f096b0AA67e9B8B1624504a63e7FD;
GUARDIAN_OLD = 0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028;

// old pool addresses
VAULT_OLD = 0xB3AC09cd5201569a821d87446A4aF1b202B10aFd;
AStox marked this conversation as resolved.
Show resolved Hide resolved

// new deployment addresses
ROOT_NEW = 0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC;
GUARDIAN_NEW = 0x09ab10a9c3E6Eac1d18270a2322B6113F4C7f5E8;
POOLMANAGER_NEW = 0x91808B5E2F6d7483D41A681034D7c9DbB64B9E29;
RESTRICTIONMANAGER_NEW = 0x4737C3f62Cc265e786b280153fC666cEA2fBc0c0;

// information to deploy the new tranche token & liquidity pool to be able to migrate the tokens
NAME = "Anemoy Liquid Treasury Fund 1";
SYMBOL = "LTF";

NAME_OLD = "DEPRECATED";
SYMBOL_OLD = "DEPRECATED";
hieronx marked this conversation as resolved.
Show resolved Hide resolved

memberlistMembers = [
0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936,
0xeF08Bb6F5F9494faf2316402802e54089E6322eb,
0x30d3bbAE8623d0e9C0db5c27B82dCDA39De40997,
0xeEDC395aAAb05e5fb6130A8C5AEbAE48E7739B78,
0x2923c1B5313F7375fdaeE80b7745106deBC1b53E,
0x14FFe68D005e58f08c27dC0c999f75639682276c,
0x86552B8d4F4a600D92d516eE8eA8B922EFEcB561
];

validUntil[0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936] = type(uint64).max;
validUntil[0xeF08Bb6F5F9494faf2316402802e54089E6322eb] = 2017150288;
validUntil[0x30d3bbAE8623d0e9C0db5c27B82dCDA39De40997] = 2017323212;
validUntil[0xeEDC395aAAb05e5fb6130A8C5AEbAE48E7739B78] = 3745713365;
validUntil[0x2923c1B5313F7375fdaeE80b7745106deBC1b53E] = 2031229099;
validUntil[0x14FFe68D005e58f08c27dC0c999f75639682276c] = 2035299660;
validUntil[0x86552B8d4F4a600D92d516eE8eA8B922EFEcB561] = 2037188261;
}
}
39 changes: 39 additions & 0 deletions src/spell/ShareMigration_NS3JR_EVM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
pragma solidity 0.8.26;

import {MigrationSpellBase} from "src/spell/MigrationSpellBase.sol";

interface ITrancheOld {
function authTransferFrom(address from, address to, uint256 value) external returns (bool);
}

contract MigrationSpell is MigrationSpellBase {
constructor() {
NETWORK = "ethereum-mainnet";
// old deployment addresses
CURRENCY_ID = 242333941209166991950178742833476896417;
ROOT_OLD = 0x498016d30Cd5f0db50d7ACE329C07313a0420502;
ADMIN_MULTISIG = 0xD9D30ab47c0f096b0AA67e9B8B1624504a63e7FD;
GUARDIAN_OLD = 0x2559998026796Ca6fd057f3aa66F2d6ecdEd9028;

// old pool addresses
VAULT_OLD = 0xd0C7E8C9b0c82b74771AE13e184432240A3a2F54;

// new deployment addresses
ROOT_NEW = 0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC;
GUARDIAN_NEW = 0x09ab10a9c3E6Eac1d18270a2322B6113F4C7f5E8;
POOLMANAGER_NEW = 0x91808B5E2F6d7483D41A681034D7c9DbB64B9E29;
RESTRICTIONMANAGER_NEW = 0x4737C3f62Cc265e786b280153fC666cEA2fBc0c0;

// information to deploy the new tranche token & liquidity pool to be able to migrate the tokens
NAME = "New Silver Series 3 Junior";
SYMBOL = "NS3JR";

NAME_OLD = "DEPRECATED";
SYMBOL_OLD = "DEPRECATED";

memberlistMembers = [0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936, 0x32f5eF78AA9C7b8882D748331AdcFe0dfA4f1a14];

validUntil[0xd595E1483c507E74E2E6A3dE8e7D08d8f6F74936] = type(uint64).max;
validUntil[0x32f5eF78AA9C7b8882D748331AdcFe0dfA4f1a14] = 2030638540;
}
}
Loading
Loading