diff --git a/.gitignore b/.gitignore
index 73ebb4f..ff476bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,9 @@
.env
.env.local
.env.production
-.env.development
+
+# test
+/deployed.json
# dependencies
/node_modules
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml
new file mode 100644
index 0000000..7dc1249
--- /dev/null
+++ b/.idea/git_toolbox_blame.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/liquid-staking-vault-cli.iml b/.idea/liquid-staking-vault-cli.iml
new file mode 100644
index 0000000..24643cc
--- /dev/null
+++ b/.idea/liquid-staking-vault-cli.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..3a9b7dc
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/abi/VaultFactory.ts b/abi/VaultFactory.ts
new file mode 100644
index 0000000..2a12328
--- /dev/null
+++ b/abi/VaultFactory.ts
@@ -0,0 +1,272 @@
+export const VaultFactoryAbi = [
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "_owner",
+ type: "address"
+ },
+ {
+ internalType: "address",
+ name: "_stakingVaultImpl",
+ type: "address"
+ },
+ {
+ internalType: "address",
+ name: "_delegationImpl",
+ type: "address"
+ }
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor"
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "implementation",
+ type: "address"
+ }
+ ],
+ name: "BeaconInvalidImplementation",
+ type: "error"
+ },
+ {
+ inputs: [],
+ name: "ERC1167FailedCreateClone",
+ type: "error"
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "owner",
+ type: "address"
+ }
+ ],
+ name: "OwnableInvalidOwner",
+ type: "error"
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "account",
+ type: "address"
+ }
+ ],
+ name: "OwnableUnauthorizedAccount",
+ type: "error"
+ },
+ {
+ inputs: [
+ {
+ internalType: "string",
+ name: "",
+ type: "string"
+ }
+ ],
+ name: "ZeroArgument",
+ type: "error"
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: "address",
+ name: "admin",
+ type: "address"
+ },
+ {
+ indexed: true,
+ internalType: "address",
+ name: "delegation",
+ type: "address"
+ }
+ ],
+ name: "DelegationCreated",
+ type: "event"
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: "address",
+ name: "previousOwner",
+ type: "address"
+ },
+ {
+ indexed: true,
+ internalType: "address",
+ name: "newOwner",
+ type: "address"
+ }
+ ],
+ name: "OwnershipTransferred",
+ type: "event"
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: "address",
+ name: "implementation",
+ type: "address"
+ }
+ ],
+ name: "Upgraded",
+ type: "event"
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: "address",
+ name: "owner",
+ type: "address"
+ },
+ {
+ indexed: true,
+ internalType: "address",
+ name: "vault",
+ type: "address"
+ }
+ ],
+ name: "VaultCreated",
+ type: "event"
+ },
+ {
+ inputs: [
+ {
+ internalType: "bytes",
+ name: "_stakingVaultParams",
+ type: "bytes"
+ },
+ {
+ components: [
+ {
+ internalType: "uint256",
+ name: "managementFee",
+ type: "uint256"
+ },
+ {
+ internalType: "uint256",
+ name: "performanceFee",
+ type: "uint256"
+ },
+ {
+ internalType: "address",
+ name: "manager",
+ type: "address"
+ },
+ {
+ internalType: "address",
+ name: "operator",
+ type: "address"
+ }
+ ],
+ internalType: "struct IDelegation.InitializationParams",
+ name: "_initializationParams",
+ type: "tuple"
+ },
+ {
+ internalType: "address",
+ name: "_lidoAgent",
+ type: "address"
+ }
+ ],
+ name: "createVault",
+ outputs: [
+ {
+ internalType: "contract IStakingVault",
+ name: "vault",
+ type: "address"
+ },
+ {
+ internalType: "contract IDelegation",
+ name: "delegation",
+ type: "address"
+ }
+ ],
+ stateMutability: "nonpayable",
+ type: "function"
+ },
+ {
+ inputs: [],
+ name: "delegationImpl",
+ outputs: [
+ {
+ internalType: "address",
+ name: "",
+ type: "address"
+ }
+ ],
+ stateMutability: "view",
+ type: "function"
+ },
+ {
+ inputs: [],
+ name: "implementation",
+ outputs: [
+ {
+ internalType: "address",
+ name: "",
+ type: "address"
+ }
+ ],
+ stateMutability: "view",
+ type: "function"
+ },
+ {
+ inputs: [],
+ name: "owner",
+ outputs: [
+ {
+ internalType: "address",
+ name: "",
+ type: "address"
+ }
+ ],
+ stateMutability: "view",
+ type: "function"
+ },
+ {
+ inputs: [],
+ name: "renounceOwnership",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function"
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "newOwner",
+ type: "address"
+ }
+ ],
+ name: "transferOwnership",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function"
+ },
+ {
+ inputs: [
+ {
+ internalType: "address",
+ name: "newImplementation",
+ type: "address"
+ }
+ ],
+ name: "upgradeTo",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function"
+ }
+] as const;
+
+
diff --git a/abi/index.ts b/abi/index.ts
index 506ac62..6d6cc60 100644
--- a/abi/index.ts
+++ b/abi/index.ts
@@ -1,2 +1,3 @@
export * from "./StakingVault";
export * from "./VaultHub";
+export * from "./VaultFactory";
diff --git a/configs/constants.ts b/configs/constants.ts
new file mode 100644
index 0000000..a9b8be7
--- /dev/null
+++ b/configs/constants.ts
@@ -0,0 +1,4 @@
+// import { Chain } from "viem/chains";
+import { holesky, mainnet } from 'viem/chains';
+
+export const SUPPORTED_CHAINS_LIST = [holesky, mainnet];
diff --git a/configs/deployed-holesky-vaults-devnet-0.json b/configs/deployed-holesky-vaults-devnet-1.json
similarity index 54%
rename from configs/deployed-holesky-vaults-devnet-0.json
rename to configs/deployed-holesky-vaults-devnet-1.json
index 5c808b0..23c4c46 100644
--- a/configs/deployed-holesky-vaults-devnet-0.json
+++ b/configs/deployed-holesky-vaults-devnet-1.json
@@ -1,54 +1,64 @@
{
"accounting": {
- "contract": "contracts/0.8.9/Accounting.sol",
- "address": "0x0AC1dA6AA962906dA7dDBE5e89fD672Cefb0AA75",
- "constructorArgs": [
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811",
- "0x1E5B4dF03cA640e5b769140B439813629A29b03a",
- "0xB5506A7438c3a928A8Cb3428c064A8049E560661"
- ]
+ "proxy": {
+ "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
+ "address": "0xa9843a9214595f97fBF3434FC0Ea408bC598f232",
+ "constructorArgs": [
+ "0x4810b7089255cfFDfd5F7dCD1997954fe1C86413",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0x"
+ ]
+ },
+ "implementation": {
+ "contract": "contracts/0.8.25/Accounting.sol",
+ "address": "0x4810b7089255cfFDfd5F7dCD1997954fe1C86413",
+ "constructorArgs": [
+ "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65",
+ "0xf8B477d407A230b4BCc0245050Ae83e91f85A61C",
+ "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA"
+ ]
+ }
},
"accountingOracle": {
"deployParameters": {
- "consensusVersion": 1
+ "consensusVersion": 2
},
"proxy": {
"contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
- "address": "0x079705e95cdffbA56bD085a601460d3A916d6deE",
+ "address": "0x4B12C08Cc2FF439c655fD72e4e1Eaf9873a15779",
"constructorArgs": [
- "0xaA44d9cab3Dc8982D3238aA2199a4894a87b02F9",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "0x3e6dE85fc813D1CD3Be8cDA399C3870631A54738",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"0x"
]
},
"implementation": {
"contract": "contracts/0.8.9/oracle/AccountingOracle.sol",
- "address": "0xaA44d9cab3Dc8982D3238aA2199a4894a87b02F9",
+ "address": "0x3e6dE85fc813D1CD3Be8cDA399C3870631A54738",
"constructorArgs": [
- "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811",
- "0x3f3B4F94e72e1d228E301d0d597838cc9636984d",
+ "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65",
+ "0x364344aE838544e3cE89424642a3FD4F168d82b8",
12,
- 1639659600
+ 1695902400
]
}
},
"apmRegistryFactory": {
"contract": "@aragon/os/contracts/factory/APMRegistryFactory.sol",
- "address": "0xeBDB38D6412Ba9B3f2A77B107e476f4164B53EAf",
+ "address": "0x6052DDB672C083B5CC0c083fFF12D027CeF55159",
"constructorArgs": [
- "0x76faff3102fFFf51396A44a3C3fCe5010B6B8cbA",
- "0x010b51303106318E2F3C6Bce9AABB2Fa450290b7",
- "0xdD2d34dD82e56b8e41311a39866F8Da26eF6CB1a",
- "0xC1C1a2B157fB41c69509450FE1D3746F7178f9d7",
- "0x794b3f32bdBA10f7513F9A751685B04Df6d8dfc3",
+ "0x558AD50d4EAD305e48CebB5a3F43a777DEd37b39",
+ "0xb89680dD40c7D9182849cb631D765eB2f407e69D",
+ "0x149D824176ECAF89855B082744E00b1c84732d6d",
+ "0x70371f312fA590c4114849aA303425d51790A84e",
+ "0x20F3A751d0877819F96092BeCB000369B9ecE268",
"0x0000000000000000000000000000000000000000"
]
},
"app:aragon-agent": {
"implementation": {
"contract": "@aragon/apps-agent/contracts/Agent.sol",
- "address": "0x96aCA063681daAe3E61B8Aa1B2952951D5184c1D",
+ "address": "0x66ac7E71FF09A36668d62167349403DAB768194A",
"constructorArgs": []
},
"aragonApp": {
@@ -57,10 +67,10 @@
"id": "0x701a4fd1f5174d12a0f1d9ad2c88d0ad11ab6aad0ac72b7d9ce621815f8016a9"
},
"proxy": {
- "address": "0xB5506A7438c3a928A8Cb3428c064A8049E560661",
+ "address": "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x701a4fd1f5174d12a0f1d9ad2c88d0ad11ab6aad0ac72b7d9ce621815f8016a9",
"0x8129fc1c"
]
@@ -69,7 +79,7 @@
"app:aragon-finance": {
"implementation": {
"contract": "@aragon/apps-finance/contracts/Finance.sol",
- "address": "0xd46ac1EFC432bD95BB9c6Bf6965544105419C765",
+ "address": "0x191c29778A3047CdfA5ce668B93aB93bb3D5E895",
"constructorArgs": []
},
"aragonApp": {
@@ -78,19 +88,19 @@
"id": "0x5c9918c99c4081ca9459c178381be71d9da40e49e151687da55099c49a4237f1"
},
"proxy": {
- "address": "0x232C8d9b0CC14f0466e24a67D95E303628152f23",
+ "address": "0xb1AE4aD42D220981368D35C12200cFea0de5Fb28",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x5c9918c99c4081ca9459c178381be71d9da40e49e151687da55099c49a4237f1",
- "0x1798de81000000000000000000000000b5506a7438c3a928a8cb3428c064a8049e5606610000000000000000000000000000000000000000000000000000000000278d00"
+ "0x1798de81000000000000000000000000d40e43682a0bf1eabbd148d17378c24e3a112cda0000000000000000000000000000000000000000000000000000000000278d00"
]
}
},
"app:aragon-token-manager": {
"implementation": {
"contract": "@aragon/apps-lido/apps/token-manager/contracts/TokenManager.sol",
- "address": "0x054E98A5e063c3d7589FF167Ab03b05cC5427324",
+ "address": "0x044035487bD1c3b77c7FF5574511D9D123FBFe22",
"constructorArgs": []
},
"aragonApp": {
@@ -99,10 +109,10 @@
"id": "0xcd567bdf93dd0f6acc3bc7f2155f83244d56a65abbfbefb763e015420102c67b"
},
"proxy": {
- "address": "0x79B48B8c15fBF4A80F6771a46af1ff49D6A7F7C7",
+ "address": "0x0cc5Ed95F24870da89ae995F272EDeb0c5Cffce6",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0xcd567bdf93dd0f6acc3bc7f2155f83244d56a65abbfbefb763e015420102c67b",
"0x"
]
@@ -111,7 +121,7 @@
"app:aragon-voting": {
"implementation": {
"contract": "@aragon/apps-lido/apps/voting/contracts/Voting.sol",
- "address": "0x0Af17BFd40b9dF93512209B17dEFF0287f51f399",
+ "address": "0x27277234aa4Cd0b8c55dA8858b802589941627ea",
"constructorArgs": []
},
"aragonApp": {
@@ -120,19 +130,19 @@
"id": "0x0abcd104777321a82b010357f20887d61247493d89d2e987ff57bcecbde00e1e"
},
"proxy": {
- "address": "0xd3835fe7E2268EaeA917106B2Ba872c686688e50",
+ "address": "0x7a55843cc05B5023aEcAcB96de07b47396248070",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x0abcd104777321a82b010357f20887d61247493d89d2e987ff57bcecbde00e1e",
- "0x13e09453000000000000000000000000b3a9b35ad7c60e1a8a0fc252bb92daea45fe346900000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000000000000000384000000000000000000000000000000000000000000000000000000000000012c"
+ "0x13e0945300000000000000000000000014b34103938e67af28bbfd2c3dd36323559c2d3d00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000000000000000384000000000000000000000000000000000000000000000000000000000000012c"
]
}
},
"app:lido": {
"implementation": {
"contract": "contracts/0.4.24/Lido.sol",
- "address": "0xA36CFE98B582A5Be4c247B5aFb7CaAa77A2bc80F",
+ "address": "0x6786CF7509043c454644B8E9a6d1d54173E320BF",
"constructorArgs": []
},
"aragonApp": {
@@ -141,10 +151,10 @@
"id": "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320"
},
"proxy": {
- "address": "0x1E5B4dF03cA640e5b769140B439813629A29b03a",
+ "address": "0xf8B477d407A230b4BCc0245050Ae83e91f85A61C",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320",
"0x"
]
@@ -153,7 +163,7 @@
"app:node-operators-registry": {
"implementation": {
"contract": "contracts/0.4.24/nos/NodeOperatorsRegistry.sol",
- "address": "0x9498c2fEf38BfeacF184EaDC5b310C2F40aA7997",
+ "address": "0x0E853A6cF06C9F0D29D92A7c27d5e03277239c1A",
"constructorArgs": []
},
"aragonApp": {
@@ -162,10 +172,10 @@
"id": "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d"
},
"proxy": {
- "address": "0x13F9Ef0CAC8679a1Edb22BACc08940828D5450A2",
+ "address": "0x1e52Ca7bE92b4CA66bF8f91716371A2487eC5EF2",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d",
"0x"
]
@@ -174,7 +184,7 @@
"app:oracle": {
"implementation": {
"contract": "contracts/0.4.24/oracle/LegacyOracle.sol",
- "address": "0xEBeD4Dd48bF50ffD3849da1AedCFEd8052162B56",
+ "address": "0x733e2affc6887f3CD879f7D74aa18ae0fcBf61c9",
"constructorArgs": []
},
"aragonApp": {
@@ -183,10 +193,10 @@
"id": "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93"
},
"proxy": {
- "address": "0x3f3B4F94e72e1d228E301d0d597838cc9636984d",
+ "address": "0x364344aE838544e3cE89424642a3FD4F168d82b8",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93",
"0x"
]
@@ -199,10 +209,10 @@
"id": "0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4"
},
"proxy": {
- "address": "0xe4deA753f8F29782E14c2a03Db8b79cd87676911",
+ "address": "0xA02c524Bf737BeAD8d703a94EFb32607330B534B",
"contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0xe1635b63b5f7b5e545f2a637558a4029dea7905361a2f0fc28c66e9136cf86a4",
"0x"
]
@@ -211,13 +221,13 @@
"aragon-acl": {
"implementation": {
"contract": "@aragon/os/contracts/acl/ACL.sol",
- "address": "0x0dC5cA1a9B671d1FF885668510d2E8BcaCC4c937",
+ "address": "0x43175FF60E2aCab56e0D79B680C6F179519c6FdB",
"constructorArgs": []
},
"proxy": {
- "address": "0xcb83f3B61e84e8C868eBa4723655a579a76C1Fb0",
+ "address": "0xBe2378978eaAfAef6fD2c2190C42C62D657c971e",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a",
"0x00"
],
@@ -231,19 +241,19 @@
"aragon-apm-registry": {
"implementation": {
"contract": "@aragon/os/contracts/apm/APMRegistry.sol",
- "address": "0x010b51303106318E2F3C6Bce9AABB2Fa450290b7",
+ "address": "0xb89680dD40c7D9182849cb631D765eB2f407e69D",
"constructorArgs": []
},
"proxy": {
- "address": "0x30bc5fd2e870B74D0036F0A652e068DF84465b4a",
+ "address": "0x8e5537a5F8a21A26cdE8D9909DB1cf638eafa7D7",
"contract": "@aragon/os/contracts/apm/APMRegistry.sol"
}
},
"aragon-evm-script-registry": {
"proxy": {
- "address": "0x1AA9F6869478fBaF138b39a510EfE12a491633Bf",
+ "address": "0x99d26EB0ABC80Dd688B5806D2d42ac8bC8475b84",
"constructorArgs": [
- "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "0x208863a96e363157D1fef5CfDa64061b3010085F",
"0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61",
"0x00"
],
@@ -254,7 +264,7 @@
"id": "0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61"
},
"implementation": {
- "address": "0xaaBd0570189Bca9C905b5DFC3f4A62A125FB3015",
+ "address": "0x3DEe956e6c65d3eA63C7cB11446bE53431946F7C",
"contract": "@aragon/os/contracts/evmscript/EVMScriptRegistry.sol",
"constructorArgs": []
}
@@ -262,27 +272,27 @@
"aragon-kernel": {
"implementation": {
"contract": "@aragon/os/contracts/kernel/Kernel.sol",
- "address": "0x812858282119C6267f466224E07A734AcA4dBbA5",
+ "address": "0x8BAaF7029C3a74c444F33e592D5c7e4B938Ed932",
"constructorArgs": [true]
},
"proxy": {
- "address": "0xDd01d45B8C7409e685a359d77d24BeA513128947",
+ "address": "0x208863a96e363157D1fef5CfDa64061b3010085F",
"contract": "@aragon/os/contracts/kernel/KernelProxy.sol",
- "constructorArgs": ["0x812858282119C6267f466224E07A734AcA4dBbA5"]
+ "constructorArgs": ["0x8BAaF7029C3a74c444F33e592D5c7e4B938Ed932"]
}
},
"aragon-repo-base": {
"contract": "@aragon/os/contracts/apm/Repo.sol",
- "address": "0xdD2d34dD82e56b8e41311a39866F8Da26eF6CB1a",
+ "address": "0x149D824176ECAF89855B082744E00b1c84732d6d",
"constructorArgs": []
},
"aragonEnsLabelName": "aragonpm",
"aragonID": {
- "address": "0xf605D4351Ed0Ab2592E58C085B4B0d1b031b2db9",
+ "address": "0xfcE523DaA916AbD5159eD139b1278e623D6EC83b",
"contract": "@aragon/id/contracts/FIFSResolvingRegistrar.sol",
"constructorArgs": [
- "0x794b3f32bdBA10f7513F9A751685B04Df6d8dfc3",
- "0xA58844869dC3c07452cDD3cf4115019875699D8D",
+ "0x20F3A751d0877819F96092BeCB000369B9ecE268",
+ "0xfa0f59C62571A4180281FBc1597b1693eF9fF579",
"0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86"
]
},
@@ -292,17 +302,17 @@
"totalNonCoverSharesBurnt": "0"
},
"contract": "contracts/0.8.9/Burner.sol",
- "address": "0xfCc2A958730f0766478a3D1AAf6Bb6964A54de80",
+ "address": "0x042C857A4043d963C2cb56d1168B86952EFAe484",
"constructorArgs": [
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811",
- "0x1E5B4dF03cA640e5b769140B439813629A29b03a",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65",
+ "0xf8B477d407A230b4BCc0245050Ae83e91f85A61C",
"0",
"0"
]
},
"callsScript": {
- "address": "0x4576eE717E00ec24fA7Bd95aca0388E30Fec3f22",
+ "address": "0xE551ceEfaa4DEb5dcDBa3307CCd12d2D7cfDbDEA",
"contract": "@aragon/os/contracts/evmscript/executors/CallsScript.sol",
"constructorArgs": []
},
@@ -310,18 +320,18 @@
"chainSpec": {
"slotsPerEpoch": 32,
"secondsPerSlot": 12,
- "genesisTime": 1639659600,
+ "genesisTime": 1695902400,
"depositContract": "0x4242424242424242424242424242424242424242"
},
- "createAppReposTx": "0xa89180c57d0991e3a420aa4cab4e0647b12651f02b2c9a936a2380b1d2ae4a3b",
+ "createAppReposTx": "0x3f1c65d8fea4c25e0827e50d37cdd63947a6117d09c7a8621e9ff77a26ff1ce9",
"daoAragonId": "lido-dao",
"daoFactory": {
- "address": "0x76faff3102fFFf51396A44a3C3fCe5010B6B8cbA",
+ "address": "0x558AD50d4EAD305e48CebB5a3F43a777DEd37b39",
"contract": "@aragon/os/contracts/factory/DAOFactory.sol",
"constructorArgs": [
- "0x812858282119C6267f466224E07A734AcA4dBbA5",
- "0x0dC5cA1a9B671d1FF885668510d2E8BcaCC4c937",
- "0x1D6BC250f5eE924BCc24b218D092d15Cd39e16A9"
+ "0x8BAaF7029C3a74c444F33e592D5c7e4B938Ed932",
+ "0x43175FF60E2aCab56e0D79B680C6F179519c6FdB",
+ "0x1142B39283A56f7e7C9596A1b26eab54442DBe7F"
]
},
"daoInitialSettings": {
@@ -341,43 +351,38 @@
"symbol": "TLDO"
}
},
- "deployer": "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "delegationImpl": {
+ "contract": "contracts/0.8.25/vaults/Delegation.sol",
+ "address": "0xac65d8Ddc91CDCE43775BA5dbF165D523D34D618",
+ "constructorArgs": ["0xf8B477d407A230b4BCc0245050Ae83e91f85A61C"]
+ },
+ "deployer": "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"depositSecurityModule": {
"deployParameters": {
- "maxDepositsPerBlock": 150,
- "minDepositBlockDistance": 5,
+ "maxOperatorsPerUnvetting": 200,
"pauseIntentValidityPeriodBlocks": 6646,
- "usePredefinedAddressInstead": null
+ "usePredefinedAddressInstead": "0x22f05077bE05be96d213C6bDBD61C8f506CcD126"
},
- "contract": "contracts/0.8.9/DepositSecurityModule.sol",
- "address": "0xc4f5Fdcc2f5f20256876947F094a7E94AfDBbA0B",
- "constructorArgs": [
- "0x1E5B4dF03cA640e5b769140B439813629A29b03a",
- "0x4242424242424242424242424242424242424242",
- "0x9Fd7Fa0615E72012C6Df1D0d46093B4b252957Cc",
- 150,
- 5,
- 6646
- ]
+ "address": "0x22f05077be05be96d213c6bdbd61c8f506ccd126"
},
"dummyEmptyContract": {
"contract": "contracts/0.8.9/utils/DummyEmptyContract.sol",
- "address": "0x368f850c98713E68F83ceB9d3852aa2a07359BAe",
+ "address": "0x176049Fa88115E6634d901eDfBe545827e1E1D2d",
"constructorArgs": []
},
"eip712StETH": {
"contract": "contracts/0.8.9/EIP712StETH.sol",
- "address": "0xA9F7C23D49494555Ff5aa1AF2a44015c4Ed6b9CA",
- "constructorArgs": ["0x1E5B4dF03cA640e5b769140B439813629A29b03a"]
+ "address": "0x7D762E9fe34Ad5a2a1f3d36daCd4C6ec66B9508D",
+ "constructorArgs": ["0xf8B477d407A230b4BCc0245050Ae83e91f85A61C"]
},
"ens": {
- "address": "0x794b3f32bdBA10f7513F9A751685B04Df6d8dfc3",
- "constructorArgs": ["0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B"],
+ "address": "0x20F3A751d0877819F96092BeCB000369B9ecE268",
+ "constructorArgs": ["0x8928cB0EdcB60806900471049719dD2EFc0bDDc1"],
"contract": "@aragon/os/contracts/lib/ens/ENS.sol"
},
"ensFactory": {
"contract": "@aragon/os/contracts/factory/ENSFactory.sol",
- "address": "0x847C07DE654a56E4a2E7Ad312Fa109e8Ef8d3739",
+ "address": "0xDEB7f630bbDDc0230793e343Ea5e16f885Bd05E7",
"constructorArgs": []
},
"ensNode": {
@@ -387,19 +392,19 @@
"ensSubdomainRegistrar": {
"implementation": {
"contract": "@aragon/os/contracts/ens/ENSSubdomainRegistrar.sol",
- "address": "0xC1C1a2B157fB41c69509450FE1D3746F7178f9d7",
+ "address": "0x70371f312fA590c4114849aA303425d51790A84e",
"constructorArgs": []
}
},
"evmScriptRegistryFactory": {
"contract": "@aragon/os/contracts/factory/EVMScriptRegistryFactory.sol",
- "address": "0x1D6BC250f5eE924BCc24b218D092d15Cd39e16A9",
+ "address": "0x1142B39283A56f7e7C9596A1b26eab54442DBe7F",
"constructorArgs": []
},
"executionLayerRewardsVault": {
"contract": "contracts/0.8.9/LidoExecutionLayerRewardsVault.sol",
- "address": "0xd4fa4434AdA6d6F7905318620CED67D940998280",
- "constructorArgs": ["0x1E5B4dF03cA640e5b769140B439813629A29b03a", "0xB5506A7438c3a928A8Cb3428c064A8049E560661"]
+ "address": "0x70D28986454Fa353dD6A6eBffe9281165505EB6c",
+ "constructorArgs": ["0xf8B477d407A230b4BCc0245050Ae83e91f85A61C", "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA"]
},
"gateSeal": {
"address": null,
@@ -414,15 +419,15 @@
"epochsPerFrame": 12
},
"contract": "contracts/0.8.9/oracle/HashConsensus.sol",
- "address": "0xc108faD7D391cEaaD9185BE04125aF8e7A6b26cD",
+ "address": "0x5E1f8Bc90bf7EB188b8f8C1E85E49b2643A6514E",
"constructorArgs": [
32,
12,
- 1639659600,
+ 1695902400,
12,
10,
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- "0x079705e95cdffbA56bD085a601460d3A916d6deE"
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0x4B12C08Cc2FF439c655fD72e4e1Eaf9873a15779"
]
},
"hashConsensusForValidatorsExitBusOracle": {
@@ -431,22 +436,22 @@
"epochsPerFrame": 4
},
"contract": "contracts/0.8.9/oracle/HashConsensus.sol",
- "address": "0x2ba358129B731066E11bae1121c13C1F6C7e5daD",
+ "address": "0x182e1A4F82312A14d823b3015C379f32094e36F6",
"constructorArgs": [
32,
12,
- 1639659600,
+ 1695902400,
4,
10,
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- "0xd4F1D70065Ef307807624fc0C6CB1fb011790823"
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0xB713d077276270dD2085aC2F2F1eeE916657952f"
]
},
"ldo": {
- "address": "0xB3A9b35Ad7C60E1A8a0fC252BB92daea45FE3469",
+ "address": "0x14B34103938E67af28BBFD2c3DD36323559C2D3D",
"contract": "@aragon/minime/contracts/MiniMeToken.sol",
"constructorArgs": [
- "0x053bA0A9Bf49FEae8Ff39Ab7987475d5d52BD9ea",
+ "0xcE3aD3640e040041D6d3F05E039c024c99048cD0",
"0x0000000000000000000000000000000000000000",
0,
"TEST Lido DAO Token",
@@ -465,64 +470,68 @@
"0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae",
"0x90a9580abeb24937fc658e497221c81ce8553b560304f9525821f32b17dbdaec"
],
- "deployTx": "0x801fe6cf2dfe2ed77bbda195754192d8b90bb12da21c3401deef9f9c119e97f5",
- "address": "0xeC64689883Daed637b933533737e231Dad1Ef238"
+ "deployTx": "0x15995278c2de902a67d1b2ba02911b70100d1537f95eab78dd207a84e9d86763",
+ "address": "0xa5691e2F7845BEc116da22b09f6A6e121f40D26d"
},
"lidoApmEnsName": "lidopm.eth",
"lidoApmEnsRegDurationSec": 94608000,
"lidoLocator": {
"proxy": {
"contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
- "address": "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811",
+ "address": "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65",
"constructorArgs": [
- "0x368f850c98713E68F83ceB9d3852aa2a07359BAe",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "0x176049Fa88115E6634d901eDfBe545827e1E1D2d",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"0x"
]
},
"implementation": {
"contract": "contracts/0.8.9/LidoLocator.sol",
- "address": "0x1c4DeB0666B6103059dF231c9e9f83b5DC3c05CD",
+ "address": "0xcd7F7aB3D3307b1624272079B68958e724207735",
"constructorArgs": [
- [
- "0x079705e95cdffbA56bD085a601460d3A916d6deE",
- "0xc4f5Fdcc2f5f20256876947F094a7E94AfDBbA0B",
- "0xd4fa4434AdA6d6F7905318620CED67D940998280",
- "0x3f3B4F94e72e1d228E301d0d597838cc9636984d",
- "0x1E5B4dF03cA640e5b769140B439813629A29b03a",
- "0xC40058aAD940f0eC1c1F54281F9B180A726B11D7",
- "0xcbcCf679706C3c8bFf1F3CE11dBe1C63B157A382",
- "0xfCc2A958730f0766478a3D1AAf6Bb6964A54de80",
- "0x9Fd7Fa0615E72012C6Df1D0d46093B4b252957Cc",
- "0xB5506A7438c3a928A8Cb3428c064A8049E560661",
- "0xd4F1D70065Ef307807624fc0C6CB1fb011790823",
- "0x4A4418BC9c06bA46C47e9Ab34a0D43f5d9EC3401",
- "0x57bbC7542B9e682CF77F32F854D18E400F53dE00",
- "0x0D691E92D5D0092A7a0D01abF42D745AA92375Ef",
- "0x0AC1dA6AA962906dA7dDBE5e89fD672Cefb0AA75"
- ]
+ {
+ "accountingOracle": "0x4B12C08Cc2FF439c655fD72e4e1Eaf9873a15779",
+ "depositSecurityModule": "0x22f05077bE05be96d213C6bDBD61C8f506CcD126",
+ "elRewardsVault": "0x70D28986454Fa353dD6A6eBffe9281165505EB6c",
+ "legacyOracle": "0x364344aE838544e3cE89424642a3FD4F168d82b8",
+ "lido": "0xf8B477d407A230b4BCc0245050Ae83e91f85A61C",
+ "oracleReportSanityChecker": "0x739e95c5FCCe141a41FEE2b7c070959f331d251D",
+ "postTokenRebaseReceiver": "0x0000000000000000000000000000000000000000",
+ "burner": "0x042C857A4043d963C2cb56d1168B86952EFAe484",
+ "stakingRouter": "0xf6F4a3eaF9a4Edd29ce8E9d41b70d87230813A14",
+ "treasury": "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA",
+ "validatorsExitBusOracle": "0xB713d077276270dD2085aC2F2F1eeE916657952f",
+ "withdrawalQueue": "0x06099Fb9769960f6877dCa51CEe9fA1e39C3A623",
+ "withdrawalVault": "0x4eE9FaE342b9D8E77C2c2DE98f55DEF8D830EEBC",
+ "oracleDaemonConfig": "0x9FEE22428742b6eE03e9cad0f09121249b49D4c6",
+ "accounting": "0xa9843a9214595f97fBF3434FC0Ea408bC598f232"
+ }
]
}
},
"lidoTemplate": {
"contract": "contracts/0.4.24/template/LidoTemplate.sol",
- "address": "0x8433fd6842A830FbFEF0FC2F1FE77cd712e6C586",
+ "address": "0x06790abb259525Ec946c6DF68E7888437BAE40f9",
"constructorArgs": [
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- "0x76faff3102fFFf51396A44a3C3fCe5010B6B8cbA",
- "0x794b3f32bdBA10f7513F9A751685B04Df6d8dfc3",
- "0x053bA0A9Bf49FEae8Ff39Ab7987475d5d52BD9ea",
- "0xf605D4351Ed0Ab2592E58C085B4B0d1b031b2db9",
- "0xeBDB38D6412Ba9B3f2A77B107e476f4164B53EAf"
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0x558AD50d4EAD305e48CebB5a3F43a777DEd37b39",
+ "0x20F3A751d0877819F96092BeCB000369B9ecE268",
+ "0xcE3aD3640e040041D6d3F05E039c024c99048cD0",
+ "0xfcE523DaA916AbD5159eD139b1278e623D6EC83b",
+ "0x6052DDB672C083B5CC0c083fFF12D027CeF55159"
],
- "deployBlock": 2598198
+ "deployBlock": 2909413
+ },
+ "lidoTemplateCreateStdAppReposTx": "0xc62a1f6ddf97e11d29cbeb13627a02e5a19bb1cb99c9c01a6506136794b12263",
+ "lidoTemplateNewDaoTx": "0xb04ecae4fdabfb8c77a55022010f52729793bfbc70100a61f6c1a75fe317be74",
+ "minFirstAllocationStrategy": {
+ "contract": "contracts/common/lib/MinFirstAllocationStrategy.sol",
+ "address": "0x99528570B420F4348519C4AB86dF5958A4BCfA11",
+ "constructorArgs": []
},
- "lidoTemplateCreateStdAppReposTx": "0x440936d67545ae94f30b534ecdf252ef85463c3b6786c48b9334a26f20997d25",
- "lidoTemplateNewDaoTx": "0xfe1b7269188f4b23f329a9a3bc695198584ed5a0afc8a50ad9486bf51dc2979b",
"miniMeTokenFactory": {
- "address": "0x053bA0A9Bf49FEae8Ff39Ab7987475d5d52BD9ea",
+ "address": "0xcE3aD3640e040041D6d3F05E039c024c99048cD0",
"contract": "@aragon/minime/contracts/MiniMeToken.sol",
- "contractName": "MiniMeTokenFactory",
"constructorArgs": []
},
"networkId": 17000,
@@ -545,70 +554,87 @@
"FINALIZATION_MAX_NEGATIVE_REBASE_EPOCH_SHIFT": 1350
},
"contract": "contracts/0.8.9/OracleDaemonConfig.sol",
- "address": "0x0D691E92D5D0092A7a0D01abF42D745AA92375Ef",
- "constructorArgs": ["0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B", []]
+ "address": "0x9FEE22428742b6eE03e9cad0f09121249b49D4c6",
+ "constructorArgs": ["0x8928cB0EdcB60806900471049719dD2EFc0bDDc1", []]
},
"oracleReportSanityChecker": {
"deployParameters": {
- "churnValidatorsPerDayLimit": 1500,
- "oneOffCLBalanceDecreaseBPLimit": 500,
+ "exitedValidatorsPerDayLimit": 1500,
+ "appearedValidatorsPerDayLimit": 1500,
+ "deprecatedOneOffCLBalanceDecreaseBPLimit": 500,
"annualBalanceIncreaseBPLimit": 1000,
"simulatedShareRateDeviationBPLimit": 250,
"maxValidatorExitRequestsPerReport": 2000,
- "maxAccountingExtraDataListItemsCount": 100,
- "maxNodeOperatorsPerExtraDataItemCount": 100,
+ "maxItemsPerExtraDataTransaction": 8,
+ "maxNodeOperatorsPerExtraDataItem": 24,
"requestTimestampMargin": 128,
- "maxPositiveTokenRebase": 5000000
+ "maxPositiveTokenRebase": 5000000,
+ "initialSlashingAmountPWei": 1000,
+ "inactivityPenaltiesAmountPWei": 101,
+ "clBalanceOraclesErrorUpperBPLimit": 50
},
"contract": "contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol",
- "address": "0xC40058aAD940f0eC1c1F54281F9B180A726B11D7",
+ "address": "0x739e95c5FCCe141a41FEE2b7c070959f331d251D",
"constructorArgs": [
- "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
- [1500, 500, 1000, 2000, 100, 100, 128, 5000000],
- [[], [], [], [], [], [], [], [], [], []]
+ "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ [1500, 1500, 1000, 2000, 8, 24, 128, 5000000, 1000, 101, 50]
]
},
- "scratchDeployGasUsed": "128397470",
+ "scratchDeployGasUsed": "135112418",
"simpleDvt": {
"deployParameters": {
- "stakingModuleTypeId": "curated-onchain-v1",
+ "stakingModuleTypeId": "simple-dvt-onchain-v1",
"stuckPenaltyDelay": 432000
}
},
"stakingRouter": {
"proxy": {
"contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
- "address": "0x9Fd7Fa0615E72012C6Df1D0d46093B4b252957Cc",
+ "address": "0xf6F4a3eaF9a4Edd29ce8E9d41b70d87230813A14",
"constructorArgs": [
- "0x2563ff1dF32A679fA5b5bb1d9081AefBf686BDC0",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "0x0436AdbF0b556d2798E66d294Dc2fEF7Cc9E6b34",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"0x"
]
},
"implementation": {
"contract": "contracts/0.8.9/StakingRouter.sol",
- "address": "0x2563ff1dF32A679fA5b5bb1d9081AefBf686BDC0",
+ "address": "0x0436AdbF0b556d2798E66d294Dc2fEF7Cc9E6b34",
"constructorArgs": ["0x4242424242424242424242424242424242424242"]
}
},
+ "stakingVaultFactory": {
+ "contract": "contracts/0.8.25/vaults/VaultFactory.sol",
+ "address": "0x2250A629B2d67549AcC89633fb394e7C7c0B9c4b",
+ "constructorArgs": [
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
+ "0x6F3c4b0A577B9fb223E831804bAAaD99de7c3Cc8",
+ "0xac65d8Ddc91CDCE43775BA5dbF165D523D34D618"
+ ]
+ },
+ "stakingVaultImpl": {
+ "contract": "contracts/0.8.25/vaults/StakingVault.sol",
+ "address": "0x6F3c4b0A577B9fb223E831804bAAaD99de7c3Cc8",
+ "constructorArgs": ["0xa9843a9214595f97fBF3434FC0Ea408bC598f232", "0x4242424242424242424242424242424242424242"]
+ },
"validatorsExitBusOracle": {
"deployParameters": {
"consensusVersion": 1
},
"proxy": {
"contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
- "address": "0xd4F1D70065Ef307807624fc0C6CB1fb011790823",
+ "address": "0xB713d077276270dD2085aC2F2F1eeE916657952f",
"constructorArgs": [
- "0x901d768A22Bf3f53cf4714e54A75F26ECaB4A419",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "0x263f466495B0BcBeFBE7220b657F5438e9155AB0",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"0x"
]
},
"implementation": {
"contract": "contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol",
- "address": "0x901d768A22Bf3f53cf4714e54A75F26ECaB4A419",
- "constructorArgs": [12, 1639659600, "0x56305bbD11C88c36ceAc6e32451DBa04b44DA811"]
+ "address": "0x263f466495B0BcBeFBE7220b657F5438e9155AB0",
+ "constructorArgs": [12, 1695902400, "0xBEC5b7D2eD56AA3040f9a80877cCF655c95F8D65"]
}
},
"vestingParams": {
@@ -617,7 +643,7 @@
"0xCD1f9954330AF39a74Fd6e7B25781B4c24ee373f": "820000000000000000000000",
"0xaa6bfBCD634EE744CB8FE522b29ADD23124593D3": "60000000000000000000000",
"0xBA59A84C6440E8cccfdb5448877E26F1A431Fc8B": "60000000000000000000000",
- "0xB5506A7438c3a928A8Cb3428c064A8049E560661": "60000000000000000000000"
+ "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA": "60000000000000000000000"
},
"start": 0,
"cliff": 0,
@@ -632,35 +658,35 @@
},
"proxy": {
"contract": "contracts/0.8.9/proxy/OssifiableProxy.sol",
- "address": "0x4A4418BC9c06bA46C47e9Ab34a0D43f5d9EC3401",
+ "address": "0x06099Fb9769960f6877dCa51CEe9fA1e39C3A623",
"constructorArgs": [
- "0x655c6400dfD52E40EacE5552126F838906dFEB34",
- "0x7D48d42F7DfcC967f7fCF54B32D5388371cD6b8B",
+ "0x37b59aEA4fFCEC7Aadd2E1D349ae8D0Fc1F24816",
+ "0x8928cB0EdcB60806900471049719dD2EFc0bDDc1",
"0x"
]
},
"implementation": {
"contract": "contracts/0.8.9/WithdrawalQueueERC721.sol",
- "address": "0x655c6400dfD52E40EacE5552126F838906dFEB34",
- "constructorArgs": ["0xA91593Ca53b802d0F0Dc0a873e811Dd219CA8cAC", "Lido: stETH Withdrawal NFT", "unstETH"]
+ "address": "0x37b59aEA4fFCEC7Aadd2E1D349ae8D0Fc1F24816",
+ "constructorArgs": ["0xA97518A4C440a0047D7b997e06F7908AbcF25b45", "Lido: stETH Withdrawal NFT", "unstETH"]
}
},
"withdrawalVault": {
"implementation": {
"contract": "contracts/0.8.9/WithdrawalVault.sol",
- "address": "0x19238F6ec1FF68ee29560326E3471b9341689881",
- "constructorArgs": ["0x1E5B4dF03cA640e5b769140B439813629A29b03a", "0xB5506A7438c3a928A8Cb3428c064A8049E560661"]
+ "address": "0xfAbDC590Bac69A7D693b8953590a622DF2C2ffb5",
+ "constructorArgs": ["0xf8B477d407A230b4BCc0245050Ae83e91f85A61C", "0xd40E43682A0Bf1EAbBD148D17378C24e3a112CdA"]
},
"proxy": {
"contract": "contracts/0.8.4/WithdrawalsManagerProxy.sol",
- "address": "0x57bbC7542B9e682CF77F32F854D18E400F53dE00",
- "constructorArgs": ["0xd3835fe7E2268EaeA917106B2Ba872c686688e50", "0x19238F6ec1FF68ee29560326E3471b9341689881"]
+ "address": "0x4eE9FaE342b9D8E77C2c2DE98f55DEF8D830EEBC",
+ "constructorArgs": ["0x7a55843cc05B5023aEcAcB96de07b47396248070", "0xfAbDC590Bac69A7D693b8953590a622DF2C2ffb5"]
},
- "address": "0x57bbC7542B9e682CF77F32F854D18E400F53dE00"
+ "address": "0x4eE9FaE342b9D8E77C2c2DE98f55DEF8D830EEBC"
},
"wstETH": {
"contract": "contracts/0.6.12/WstETH.sol",
- "address": "0xA91593Ca53b802d0F0Dc0a873e811Dd219CA8cAC",
- "constructorArgs": ["0x1E5B4dF03cA640e5b769140B439813629A29b03a"]
+ "address": "0xA97518A4C440a0047D7b997e06F7908AbcF25b45",
+ "constructorArgs": ["0xf8B477d407A230b4BCc0245050Ae83e91f85A61C"]
}
}
diff --git a/configs/deployed.ts b/configs/deployed.ts
index f894b03..156f294 100644
--- a/configs/deployed.ts
+++ b/configs/deployed.ts
@@ -1,32 +1,100 @@
import { lstatSync } from "fs";
import { resolve } from "path";
+import { zeroAddress, Address, Chain } from "viem";
+import { getValueByPath, resolvePath, validateConfig } from "@utils";
+import { JSONConfig } from "@types";
import { envs } from "./envs";
-import { getValueByPath } from "@utils";
-import { zeroAddress, Address } from "viem";
+import { SUPPORTED_CHAINS_LIST } from "./constants";
-export const importConfigFile = (path?: string) => {
- const fullPath = resolve("configs", path ?? "");
- const json: Record> = {};
+export const importDeployFile = () => {
+ const fullPath = resolve("configs", envs?.DEPLOYED ?? "");
+ if (!fullPath) {
+ throw new Error("Deployed contracts file is not set, check .env file");
+ }
+
+ let json: Record = {};
if (lstatSync(fullPath).isFile()) {
- // eslint-disable-next-line @typescript-eslint/no-var-requires
- Object.assign(json, require(fullPath));
+ json = structuredClone(require(fullPath));
}
return json;
};
-export const getContracts = () => {
- const deployedFile = envs?.DEPLOYED;
+export const importConfigFile = () => {
+ const path = envs?.CONFIG ?? '';
+ const fullPath = resolvePath(path, __dirname);
- if (!deployedFile) {
- throw new Error("Deployed contracts file is not set, check .env file");
+ let json = {} as JSONConfig;
+
+ if (lstatSync(fullPath).isFile()) {
+ json = structuredClone(require(fullPath));
+ }
+
+ return json;
+};
+
+export const getConfig = (() => {
+ const configJSON = importConfigFile();
+ const errors = validateConfig(configJSON as unknown as JSONConfig);
+ const errorKeys = Object.keys(errors);
+ if (errorKeys.length > 0) {
+ errorKeys.forEach((key) => console.error(`${errors[key as keyof JSONConfig]}`));
+ return () => null;
+ }
+
+ return () => configJSON;
+})();
+
+export const getDeployed = (() => {
+ const deployedJSON = importDeployFile();
+
+ return () => deployedJSON;
+})();
+
+export const getChainId = (() => {
+ let chainId: number;
+ const config = getConfig();
+ const deployed = getDeployed();
+
+ if (config) {
+ chainId = config.chainId as number;
+ } else if (deployed.chainId) {
+ chainId = deployed.chainId;
+ } else {
+ chainId = Number(process.env.CHAIN_ID);
+ }
+
+ return () => chainId;
+})();
+
+export const getChain = (chainId?: number): Chain => {
+ const id = chainId ?? getChainId();
+ const chain = SUPPORTED_CHAINS_LIST.find(chain => chain.id === id);
+ return chain ?? SUPPORTED_CHAINS_LIST[0] as Chain;
+};
+
+export const getRpcUrl = (() => {
+ let rpcUrl: string;
+ const config = getConfig();
+
+ if (config) {
+ rpcUrl = config.rpcLink as string;
}
- const mainDeployedJSON = importConfigFile(envs?.DEPLOYED);
- const extraDeployedJSON = importConfigFile(`extra-${envs?.DEPLOYED}`);
+ return () => rpcUrl;
+})();
+
+export const getContracts = () => {
+ const config = getConfig();
+ const deployedJSON = getDeployed();
+
+ if (config) {
+ const { lidoLocator, accounting } = config;
+ return { ...deployedJSON, lidoLocator, accounting }
+ }
- return { ...mainDeployedJSON, ...extraDeployedJSON };
+ return { ...deployedJSON };
};
export const getContractDeploy = (path: string) => {
@@ -47,8 +115,8 @@ export const getDeployedAddress = (...contractKeys: string[]) => {
throw new Error(`Contracts by ${contractKeys} not found`);
}
- if ("proxyAddress" in contract) {
- return contract.proxyAddress as Address;
+ if ("proxy" in contract && typeof contract.proxy === 'object' && "address" in contract.proxy!) {
+ return contract.proxy.address as Address;
}
if ("address" in contract) {
@@ -70,22 +138,22 @@ export const getAddressMap = () => {
const contracts = getContracts();
return Object.entries(contracts).reduce((acc, [key, value]) => {
- const name = value.contract || key;
- const proxyAddress =
- value.proxyAddress || (value.implementation && value.address);
- const implementation = value.implementation;
- const isNotProxy = !implementation && !proxyAddress;
-
- if (proxyAddress) {
- acc[proxyAddress.toLowerCase()] = `Proxy (${name})`;
+ const name = value?.contract || key;
+ const proxy =
+ value?.proxy || (value?.implementation && value?.address);
+ const implementation = value?.implementation.address;
+ const isNotProxy = !implementation && !proxy;
+
+ if (proxy) {
+ acc[proxy.toLowerCase()] = `Proxy (${name})`;
}
if (implementation) {
acc[implementation.toLowerCase()] = `Implementation (${name})`;
}
- if (isNotProxy && value.address) {
- acc[value.address.toLowerCase()] = name;
+ if (isNotProxy && value?.address) {
+ acc[value?.address.toLowerCase()] = name;
}
return acc;
diff --git a/configs/envs.ts b/configs/envs.ts
index 90b249b..1f529c9 100644
--- a/configs/envs.ts
+++ b/configs/envs.ts
@@ -2,15 +2,12 @@ import * as dotenv from "dotenv";
const { parsed } = dotenv.config();
-export const envs = parsed;
+export const envs = structuredClone(parsed);
if (envs) {
- envs.DEPLOYED = envs?.DEPLOYED || (process.env.DEPLOYED as string);
- envs.RPC_URL_1 = envs?.RPC_URL_1 || (process.env.RPC_URL_1 as string);
- envs.RPC_URL_17000 =
- envs?.RPC_URL_17000 || (process.env.RPC_URL_17000 as string);
-
- envs.PRIVATE_KEY_1 =
- envs?.PRIVATE_KEY_1 || (process.env.PRIVATE_KEY_1 as string);
- envs.PRIVATE_KEY_17000 =
- envs?.PRIVATE_KEY_137 || (process.env.PRIVATE_KEY_137 as string);
+ envs.DEPLOYED = (process.env.DEPLOYED as string) ?? envs?.DEPLOYED;
+ envs.CONFIG = (process.env.CONFIG as string) ?? envs?.CONFIG ;
+ envs.RPC_URL_1 = (process.env.RPC_URL_1 as string) ?? envs?.RPC_URL_1;
+ envs.RPC_URL_17000 = (process.env.RPC_URL_17000 as string) ?? envs?.RPC_URL_17000;
+ envs.PRIVATE_KEY_1 = (process.env.PRIVATE_KEY_1 as string) ?? envs?.PRIVATE_KEY_1;
+ envs.PRIVATE_KEY_17000 = (process.env.PRIVATE_KEY_17000 as string) ?? envs?.PRIVATE_KEY_17000;
}
diff --git a/configs/extra-deployed-holesky-vaults-devnet-0.json b/configs/extra-deployed-holesky-vaults-devnet-1.json
similarity index 100%
rename from configs/extra-deployed-holesky-vaults-devnet-0.json
rename to configs/extra-deployed-holesky-vaults-devnet-1.json
diff --git a/contracts/index.ts b/contracts/index.ts
index 5c5bf23..320bf1d 100644
--- a/contracts/index.ts
+++ b/contracts/index.ts
@@ -1,2 +1,3 @@
export * from "./vault-hub";
+export * from "./vault-factory";
export * from "./vault";
diff --git a/contracts/vault-factory.ts b/contracts/vault-factory.ts
new file mode 100644
index 0000000..3971c8f
--- /dev/null
+++ b/contracts/vault-factory.ts
@@ -0,0 +1,17 @@
+import { getContract, createPublicClient, http } from "viem";
+import { VaultFactoryAbi } from "abi";
+import { getDeployedAddress, envs, getRpcUrl, getChain } from "@configs";
+
+export const getVaultFactoryContract = (chainId: number) => {
+ const rpcUrls = getRpcUrl() ?? envs?.[`RPC_URL_${chainId}`];
+ const url = rpcUrls.split(',')[0];
+
+ return getContract({
+ address: getDeployedAddress("stakingVaultFactory"),
+ abi: VaultFactoryAbi,
+ client: createPublicClient({
+ chain: getChain(chainId),
+ transport: http(url),
+ }),
+ });
+};
diff --git a/contracts/vault-hub.ts b/contracts/vault-hub.ts
index b0c7944..6bb81b4 100644
--- a/contracts/vault-hub.ts
+++ b/contracts/vault-hub.ts
@@ -1,18 +1,16 @@
-import { getContract, createPublicClient, http, Chain } from "viem";
+import { getContract, createPublicClient, http } from "viem";
import { VaultHubAbi } from "abi";
-import { getDeployedAddress, envs } from "@configs";
+import {getDeployedAddress, envs, getChain} from "@configs";
-export const getVaultHubContract = (chainId?: Chain) => {
+export const getVaultHubContract = (chainId?: number) => {
const rpcUrl = envs?.[`RPC_URL_${chainId || process.env.CHAIN_ID}`];
- const vaultHubContract = getContract({
+ return getContract({
address: getDeployedAddress("accounting"),
abi: VaultHubAbi,
client: createPublicClient({
- chain: chainId,
+ chain: getChain(chainId),
transport: http(rpcUrl),
}),
});
-
- return vaultHubContract;
};
diff --git a/contracts/vault.ts b/contracts/vault.ts
index c09917a..389ebbe 100644
--- a/contracts/vault.ts
+++ b/contracts/vault.ts
@@ -5,7 +5,7 @@ import { envs } from "@configs";
export const getStakingVaultContract = (address: Address, chainId?: Chain) => {
const rpcUrl = envs?.[`RPC_URL_${chainId || process.env.CHAIN_ID}`];
- const vaultHubContract = getContract({
+ return getContract({
address,
abi: StakingVaultAbi,
client: createPublicClient({
@@ -13,6 +13,4 @@ export const getStakingVaultContract = (address: Address, chainId?: Chain) => {
transport: http(rpcUrl),
}),
});
-
- return vaultHubContract;
};
diff --git a/features/index.ts b/features/index.ts
new file mode 100644
index 0000000..f5444af
--- /dev/null
+++ b/features/index.ts
@@ -0,0 +1 @@
+export * from './vault-factory';
diff --git a/features/vault-factory.ts b/features/vault-factory.ts
new file mode 100644
index 0000000..bc816c1
--- /dev/null
+++ b/features/vault-factory.ts
@@ -0,0 +1,36 @@
+import {getChain, getChainId, getDeployedAddress} from "@configs";
+import { getAccount } from "@providers";
+import { VaultPayload } from "@types";
+import { getVaultFactoryContract } from "@contracts";
+
+export async function* createVault({
+ chainId,
+ manager,
+ operator,
+ quantity,
+ managementFee,
+ performanceFee,
+}: VaultPayload) {
+ const id = chainId ?? getChainId()
+ const contract = getVaultFactoryContract(id);
+ const chain = getChain(id);
+
+ for (let _ of Array.from(Array(quantity))) {
+ yield await contract.write.createVault(
+ [
+ '0x',
+ {
+ managementFee,
+ performanceFee,
+ manager,
+ operator,
+ },
+ getDeployedAddress('app:aragon-agent'),
+ ],
+ {
+ account: getAccount(chain.id),
+ chain,
+ }
+ );
+ }
+}
diff --git a/package.json b/package.json
index bbb7d19..93dec3c 100644
--- a/package.json
+++ b/package.json
@@ -34,12 +34,12 @@
},
"devDependencies": {
"@swc/core": "^1.7.42",
- "@types/node": "^22.8.5",
+ "@types/node": "^22.10.2",
"semantic-release": "^24.2.0",
"ts-node": "^10.9.2",
"tsc-alias": "^1.8.10",
"tsconfig-paths": "^4.2.0",
- "typescript": "^5.6.3"
+ "typescript": "^5.7.2"
},
"release": {
"branches": [
diff --git a/programs/config.ts b/programs/config.ts
new file mode 100644
index 0000000..d04bfd3
--- /dev/null
+++ b/programs/config.ts
@@ -0,0 +1,35 @@
+import { readFileSync, existsSync } from "node:fs";
+import { resolve } from "node:path";
+
+import { program } from "@command";
+import { validateConfig } from "@utils";
+import { JSONConfig } from "@types";
+
+program
+ .command('conf ')
+ .description('Load and validate a JSON configuration file')
+ .action((filePath) => {
+ try {
+ const absolutePath = resolve(filePath);
+ if (!existsSync(absolutePath)) {
+ program.error(`File not found: ${absolutePath}`, { exitCode: 1 });
+ }
+
+ const rawData = readFileSync(absolutePath, 'utf-8');
+ const config = JSON.parse(rawData);
+
+ const errors = validateConfig(config);
+ const errorKeys = Object.keys(errors);
+ if (errorKeys.length > 0) {
+ errorKeys.forEach((key) => program.error(`${key} - ${errors[key as keyof JSONConfig]}`));
+ process.exit(1);
+ }
+
+ console.log('Configuration is valid!');
+ } catch (error) {
+ if (error instanceof Error) {
+ console.error('Error loading or validating JSON file:', error.message);
+ }
+ process.exit(1);
+ }
+ });
diff --git a/programs/index.ts b/programs/index.ts
index 5c5bf23..ab0d75c 100644
--- a/programs/index.ts
+++ b/programs/index.ts
@@ -1,2 +1,3 @@
export * from "./vault-hub";
export * from "./vault";
+export * from "./vault-factory";
diff --git a/programs/vault-factory.ts b/programs/vault-factory.ts
new file mode 100644
index 0000000..5754b9a
--- /dev/null
+++ b/programs/vault-factory.ts
@@ -0,0 +1,59 @@
+import { Address, isAddress, isAddressEqual } from "viem";
+import { program } from "@command";
+import { ChainOption } from "@types";
+import { createVault } from "@features";
+
+const vaultFactory = program.command("vf").description("vault factory contract");
+
+vaultFactory
+ .command("create-vault")
+ .description("create vault contract and assign manager and operator")
+ .option("-c, --chainId ", "chainId")
+ .option("-m, --manager ", "manager address")
+ .option("-o, --operator ", "operator address")
+ .option("-q, --quantity ", "quantity of vaults to create, default 1, max 10")
+ .argument("", "Vault owner fee, for e.g. 100 == 1%")
+ .argument("", "Node operator fee, for e.g. 100 == 1%")
+ .action(
+ async (
+ ownerFee: string,
+ operatorFee: string,
+ { chainId, manager, operator, quantity = '1' }: ChainOption & { manager: Address, operator: Address, quantity: string }
+ ) => {
+ const managementFee = BigInt(ownerFee);
+ const performanceFee = BigInt(operatorFee);
+ const qnt = parseInt(quantity);
+
+ if (!isAddress(manager)) {
+ program.error("manager address is not valid", { exitCode: 1 });
+ }
+
+ if (!isAddress(operator)) {
+ program.error("operator address is not valid", { exitCode: 1 });
+ }
+
+ if (isAddressEqual(manager, operator)) {
+ program.error("manager address can't be equal operator address", { exitCode: 1 });
+ }
+
+ if (isNaN(qnt)) {
+ program.error("quantity must be a number", { exitCode: 1 });
+ }
+
+ const payload = {
+ quantity: qnt,
+ chainId,
+ manager,
+ operator,
+ managementFee,
+ performanceFee,
+ }
+
+ const transactions = []
+ for await (const tx of createVault(payload)) {
+ transactions.push(tx);
+ }
+
+ console.table(transactions);
+ }
+ );
diff --git a/programs/vault-hub.ts b/programs/vault-hub.ts
index eb78787..1936816 100644
--- a/programs/vault-hub.ts
+++ b/programs/vault-hub.ts
@@ -1,21 +1,35 @@
+import { Address } from "viem";
import { program } from "@command";
import { getVaultHubContract } from "@contracts";
import { getAccount } from "@providers";
+import { ChainOption } from "@types";
+import {getChain} from "@configs";
const vaultHub = program.command("vh").description("vault hub contract");
+// constants - get vault hub constants
+// v-count - get vaults count
+// vi - get vault and vault socket by index
+// va - get vault socket by address
+// v-connect - connects a vault to the hub
+// v-force-rebalance - force rebalance of the vault to have sufficient reserve ratio
+// v-role-admin - returns the admin role that controls `role`
+// v-role-member - returns one of the accounts that have `role`
+// v-role-member-count - returns the number of accounts that have `role`
+// v-role-has - returns `true` if `account` has been granted `role`
+
vaultHub
.command("constants")
.description("get vault hub constants")
.option("-c, --chainId ", "chainId")
- .action(async ({ chainId }) => {
+ .action(async ({ chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const VAULT_MASTER_ROLE = await contract.read.VAULT_MASTER_ROLE();
const DEFAULT_ADMIN_ROLE = await contract.read.DEFAULT_ADMIN_ROLE();
const STETH = await contract.read.stETH();
const TREASURY = await contract.read.treasury();
- const address = await contract.address;
+ const address = contract.address;
console.table({
VAULT_MASTER_ROLE,
@@ -30,7 +44,7 @@ vaultHub
.command("v-count")
.description("get vaults count")
.option("-c, --chainId ", "chainId")
- .action(async ({ chainId }) => {
+ .action(async ({ chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const vaultsCount = await contract.read.vaultsCount();
@@ -41,22 +55,35 @@ vaultHub
});
vaultHub
- .command("v")
- .description("get vault")
+ .command("vi")
+ .description("get vault and vault socket by index")
.option("-c, --chainId ", "chainId")
.argument("", "index")
- .action(async (index, { chainId }) => {
+ .action(async (index: readonly [bigint], { chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const vault = await contract.read.vault(index);
const vaultSocket = await contract.read.vaultSocket(index);
console.table({
- vault,
- vaultSocket,
+ Vault: vault,
+ "Vault Socket": vaultSocket,
});
});
+vaultHub
+ .command("va")
+ .description("get vault socket by address")
+ .option("-c, --chainId ", "chainId")
+ .argument("", "address")
+ .action(async (address: readonly [Address], { chainId }: ChainOption) => {
+ const contract = getVaultHubContract(chainId);
+
+ const vaultSocket = await contract.read.vaultSocket(address);
+
+ console.table({ "Vault Socket": vaultSocket });
+ });
+
vaultHub
.command("v-connect")
.description("connects a vault to the hub")
@@ -74,12 +101,12 @@ vaultHub
.argument("", "treasury fee in basis points")
.action(
async (
- vault,
- shareLimit,
- reserveRatio,
- reserveRatioThreshold,
- treasuryFeeBP,
- { chainId }
+ vault: Address,
+ shareLimit: bigint,
+ reserveRatio: bigint,
+ reserveRatioThreshold: bigint,
+ treasuryFeeBP: bigint,
+ { chainId }: ChainOption
) => {
const contract = getVaultHubContract(chainId);
@@ -87,13 +114,11 @@ vaultHub
[vault, shareLimit, reserveRatio, reserveRatioThreshold, treasuryFeeBP],
{
account: getAccount(chainId),
- chain: chainId,
+ chain: getChain(chainId),
}
);
- console.table({
- Transaction: tx,
- });
+ console.table({ Transaction: tx });
}
);
@@ -102,12 +127,12 @@ vaultHub
.description("force rebalance of the vault to have sufficient reserve ratio")
.option("-c, --chainId ", "chainId")
.argument("", "vault address")
- .action(async (vault, { chainId }) => {
+ .action(async (vault: Address, { chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const tx = await contract.write.forceRebalance([vault], {
account: getAccount(chainId),
- chain: chainId,
+ chain: getChain(chainId),
});
console.table({
@@ -121,7 +146,7 @@ vaultHub
.description("returns the admin role that controls `role`")
.option("-c, --chainId ", "chainId")
.argument("", "role")
- .action(async (role, { chainId }) => {
+ .action(async (role: readonly [Address], { chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const roleAdmin = await contract.read.getRoleAdmin(role);
@@ -137,7 +162,11 @@ vaultHub
.option("-c, --chainId ", "chainId")
.argument("", "role")
.argument("", "index")
- .action(async (role, index, { chainId }) => {
+ .action(async (
+ role: readonly [Address, bigint],
+ index,
+ { chainId }: ChainOption
+ ) => {
const contract = getVaultHubContract(chainId);
const roleMember = await contract.read.getRoleMember(role, index);
@@ -153,7 +182,7 @@ vaultHub
.option("-c, --chainId ", "chainId")
.argument("", "role")
.argument("", "index")
- .action(async (role, index, { chainId }) => {
+ .action(async (role: readonly [Address], index, { chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const roleMemberCount = await contract.read.getRoleMemberCount(role, index);
@@ -169,7 +198,7 @@ vaultHub
.option("-c, --chainId ", "chainId")
.argument("", "role")
.argument("", "account")
- .action(async (role, account, { chainId }) => {
+ .action(async (role: readonly [Address, Address], account, { chainId }: ChainOption) => {
const contract = getVaultHubContract(chainId);
const roleHas = await contract.read.hasRole(role, account);
diff --git a/programs/vault.ts b/programs/vault.ts
index edd5578..69b90f8 100644
--- a/programs/vault.ts
+++ b/programs/vault.ts
@@ -1,11 +1,27 @@
import { program } from "@command";
import { getStakingVaultContract } from "@contracts";
import { getAccount } from "@providers";
-import { parseEther } from "viem";
+import {Address, parseEther} from "viem";
const vault = program.command("v").description("vault contract");
// Views
+// info - get vault base info
+// l-report - get latest vault report
+// valuation - get vault valuation
+// is-healthy - get vault isHealthy
+// unlocked - get vault unlocked
+// wc - get vault withdrawal credentials
+// fund - fund vault
+// withdraw - withdraw from vault
+// rebalance - rebalance vault // ??
+// no-deposit-beacon -deposit to beacon chain
+// no-val-exit - request to exit validator
+
+// ? - quick creation any number of Vaults
+// delta - inOutDelta
+// ? - connect Vaults to VaultHub through protocol voting
+// ? - change user permissions / roles by quorum of a pair of addresses
vault
.command("info")
@@ -97,7 +113,6 @@ vault
});
// Functions
-
vault
.command("fund")
.description("fund vault")
@@ -152,7 +167,6 @@ vault
});
// NOs
-
vault
.command("no-deposit-beacon")
.description("deposit to beacon chain")
@@ -191,3 +205,16 @@ vault
console.table({ Transaction: tx });
});
+
+vault
+ .command("delta")
+ .description("the net difference between deposits and withdrawals")
+ .argument("", "vault address")
+ .option("-c, --chainId ", "chainId")
+ .action(async (vault: Address, { chainId }) => {
+ const contract = getStakingVaultContract(vault, chainId);
+
+ const inOutDelta = await contract.read.inOutDelta();
+
+ console.table({ 'In Out Delta': inOutDelta });
+ });
diff --git a/providers/wallet.ts b/providers/wallet.ts
index 48aa4eb..15528b8 100644
--- a/providers/wallet.ts
+++ b/providers/wallet.ts
@@ -1,37 +1,40 @@
-import { Address, Chain, createWalletClient, http } from "viem";
+import { Address, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
-import { envs } from "@configs";
+import { envs, getConfig, getChainId, getRpcUrl, getChain } from "@configs";
-export const getWalletClient = (chainId?: Chain) => {
- const rpcUrl = envs?.[`RPC_URL_${chainId || process.env.CHAIN_ID}`];
+export const getWalletClient = (chainId?: number) => {
+ const id = getChainId() ?? chainId;
+ const rpcUrls = getRpcUrl() ?? envs?.[`RPC_URL_${id}`];
+ const url = rpcUrls.split(',')[0];
const client = createWalletClient({
- chain: chainId,
- transport: http(rpcUrl),
+ chain: getChain(id),
+ transport: http(url),
});
return client;
};
-export const getAccount = (chainId?: Chain) => {
- const privateKey = envs?.[`PRIVATE_KEY_${chainId || process.env.CHAIN_ID}`];
+export const getAccount = (chainId?: number) => {
+ const config = getConfig();
+ const id = chainId ?? getChainId();
+ const privateKey = config?.privateKey ?? envs?.[`PRIVATE_KEY_${id}`];
if (!privateKey) {
- throw new Error(`PRIVATE_KEY_${chainId} is not set`);
+ throw new Error(`Private key for ${id} chain is not set`);
}
- const account = privateKeyToAccount(privateKey as Address);
-
- return account;
+ return privateKeyToAccount(privateKey as Address);
};
-export const getWalletWithAccount = (chainId?: Chain) => {
+export const getWalletWithAccount = (chainId?: number) => {
const rpcUrl = envs?.[`RPC_URL_${chainId || process.env.CHAIN_ID}`];
+ const id = chainId ?? getChainId();
- const account = getAccount(chainId);
+ const account = getAccount(id);
const client = createWalletClient({
account,
- chain: chainId,
+ chain: getChain(id),
transport: http(rpcUrl),
});
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..3a10310
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+yarn --silent node ./dist/index.js "$@"
diff --git a/tsconfig.json b/tsconfig.json
index 744ad82..e2092e7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -25,7 +25,9 @@
"@scripts": ["scripts"],
"@utils": ["utils"],
"@abi": ["abi"],
- "@providers": ["providers"]
+ "@providers": ["providers"],
+ "@features": ["features"],
+ "@types": ["types"]
},
"outDir": "dist",
"sourceMap": true,
diff --git a/types/common.ts b/types/common.ts
new file mode 100644
index 0000000..dffe0fc
--- /dev/null
+++ b/types/common.ts
@@ -0,0 +1,10 @@
+export type ChainOption = { chainId: number };
+
+export interface VaultPayload {
+ chainId: number;
+ manager: string;
+ operator: string;
+ quantity: number;
+ managementFee: bigint;
+ performanceFee: bigint;
+}
diff --git a/types/config.ts b/types/config.ts
new file mode 100644
index 0000000..77f491c
--- /dev/null
+++ b/types/config.ts
@@ -0,0 +1,7 @@
+export interface JSONConfig {
+ rpcLink: string | undefined;
+ privateKey: string | undefined;
+ chainId: number | undefined;
+ lidoLocator: string | undefined;
+ accounting: string | undefined;
+}
diff --git a/types/index.ts b/types/index.ts
new file mode 100644
index 0000000..82e9bc5
--- /dev/null
+++ b/types/index.ts
@@ -0,0 +1,2 @@
+export * from "./config";
+export * from "./common";
diff --git a/utils/data-validators.ts b/utils/data-validators.ts
new file mode 100644
index 0000000..f3aeca8
--- /dev/null
+++ b/utils/data-validators.ts
@@ -0,0 +1,47 @@
+import { isAddress } from "viem";
+
+import { JSONConfig } from "@types";
+
+export const validateConfig = (config: JSONConfig) => {
+ const errors = {} as Record;
+
+ if (!isValidUrl(config.rpcLink)) {
+ errors.rpcLink = 'Invalid rpcLink: must be a valid URL.';
+ }
+
+ if (typeof config.privateKey !== 'string' || !config.privateKey) {
+ errors.privateKey = 'Invalid privateKey: must be a non-empty string.';
+ }
+
+ if (typeof config.chainId !== 'number' || isNaN(config.chainId)) {
+ errors.chainId = 'Invalid chainId: must be a string representing a number.';
+ }
+
+ if (typeof config.lidoLocator !== 'string' || !isAddress(config.lidoLocator)) {
+ errors.lidoLocator = 'Invalid lidoLocator: must be a valid Ethereum address.';
+ }
+
+ if (typeof config.accounting !== 'string' || !isAddress(config.accounting)) {
+ errors.accounting = 'Invalid accounting: must be a valid Ethereum address.';
+ }
+
+ return errors;
+}
+
+export const isValidUrl = (value: string | undefined): boolean => {
+ if (!value) {
+ return false;
+ }
+
+ if ('canParse' in URL) {
+ return URL.canParse(value);
+ }
+
+ try {
+ // used global here to avid types issue
+ new global.URL(value);
+ return true;
+ } catch {
+ return false;
+ }
+}
diff --git a/utils/index.ts b/utils/index.ts
index 50816ce..bc91468 100644
--- a/utils/index.ts
+++ b/utils/index.ts
@@ -1 +1,3 @@
export * from "./get-value";
+export * from "./data-validators";
+export * from "./resolve-path";
diff --git a/utils/resolve-path.ts b/utils/resolve-path.ts
new file mode 100644
index 0000000..45c15ca
--- /dev/null
+++ b/utils/resolve-path.ts
@@ -0,0 +1,10 @@
+import { isAbsolute, join, resolve } from "path";
+import { homedir } from "os";
+
+export function resolvePath(path: string, dir: string ) {
+ return path.startsWith('~')
+ ? join(homedir(), path.slice(1))
+ : isAbsolute(path)
+ ? path
+ : resolve(dir, path);
+}
diff --git a/yarn.lock b/yarn.lock
index 5404467..b7c2752 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -738,12 +738,12 @@
"@tufjs/canonical-json" "2.0.0"
minimatch "^9.0.5"
-"@types/node@^22.8.5":
- version "22.8.5"
- resolved "https://registry.npmjs.org/@types/node/-/node-22.8.5.tgz"
- integrity sha512-5iYk6AMPtsMbkZqCO1UGF9W5L38twq11S2pYWkybGHH2ogPUvXWNlQqJBzuEZWKj/WRH+QTeiv6ySWqJtvIEgA==
+"@types/node@^22.10.2":
+ version "22.10.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9"
+ integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==
dependencies:
- undici-types "~6.19.8"
+ undici-types "~6.20.0"
"@types/normalize-package-data@^2.4.3":
version "2.4.4"
@@ -3546,20 +3546,20 @@ type-fest@^4.6.0, type-fest@^4.7.1:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz"
integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==
-typescript@^5.6.3:
- version "5.6.3"
- resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz"
- integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
+typescript@^5.7.2:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
+ integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
uglify-js@^3.1.4:
version "3.19.3"
resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz"
integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==
-undici-types@~6.19.8:
- version "6.19.8"
- resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz"
- integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
+undici-types@~6.20.0:
+ version "6.20.0"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
+ integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
unicode-emoji-modifier-base@^1.0.0:
version "1.0.0"