diff --git a/.gitmodules b/.gitmodules index 75cd8bf20..44f0f748e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,4 +17,4 @@ [submodule "lib/eigenlayer-contracts"] path = lib/eigenlayer-contracts url = https://github.com/layr-labs/eigenlayer-contracts - commit = bda003385c5fec59e35196dc14d01f17d1eb7001 \ No newline at end of file + commit = bda003385c5fec59e35196dc14d01f17d1eb7001 diff --git a/README.md b/README.md index 41e30b23d..7d176d63b 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,6 @@ | ynETH Redemption Assets Vault | [`0xF0207Ffa0b793E009DF9Df62fEE95B8FC6c93EcF`](https://etherscan.io/address/0x5D6e53c42E3B37f82F693937BC508940769c5caf) | | WithdrawalsProcessor | [`0x61810a90128ee5c5f5a3730f0449da9e9480f888`](https://etherscan.io/address/0x6d052CdEd3F64aea51f6051F33b68b42016C5FbA) | - - - - ## Holesky ### Contracts diff --git a/deployments/YnLSDe-1.json b/deployments/YnLSDe-1.json index b1b7c43b0..cd1eb868b 100644 --- a/deployments/YnLSDe-1.json +++ b/deployments/YnLSDe-1.json @@ -11,13 +11,16 @@ "UNPAUSE_ADMIN": "0xfcad670592a3b24869C0b51a6c6FDED4F95D6975", "YNDev": "0xa08F39d30dc865CC11a49b6e5cBd27630D6141C3", "YnSecurityCouncil": "0xfcad670592a3b24869C0b51a6c6FDED4F95D6975", - "implementation-ynLSDe": "0x3688bAce1C507b368b5061F97cB48037f0Df6b2f", - "implementation-assetRegistry": "0x84dA5aB890B0a3314deEd0BeBd2463309a755EAc", - "implementation-eigenStrategyManager": "0xE2343a850394ee1b1e33b16Da5bD73B076D6Fa81", + "implementation-ynLSDe": "0x989C5E2509C501deB6195b9f525d9092514041b4", + "implementation-assetRegistry": "0x94db8f0d5bBCCEBF6d8288d06eb53bB80cA125bd", + "implementation-eigenStrategyManager": "0x1776deA5799fc7ad10b6039f6E1927fEfd731E85", "implementation-rateProvider": "0xAEDC83F607126b4D2437F79285e2C635685BBA01", - "implementation-tokenStakingNodesManager": "0x17e77F964538fed3ADEc3E8dBB6147dA258206Da", - "implementation-ynEigenDepositAdapter": "0xA9CD5a5199177b704287e379e85af95F0f061Bf2", + "implementation-tokenStakingNodesManager": "0x81f34d0DB58A7934549D9B2B1E76542ED9801B1f", + "implementation-ynEigenDepositAdapter": "0x8Ef7a066bf2Cf76baD826C1De8D314badF057b52", "implementation-ynEigenViewer": "0x95046553147036dA98Aecc02B2526FCBc36F4306", + "implementation-redemptionAssetsVault": "0x9892A40FE6e17d4C88a92b2e37c12981bAA6F14A", + "implementation-withdrawalQueueManager": "0xaac93A4ddE34CE9ad9dD8556B9faDd83380a5D64", + "implementation-wrapper": "0x7C31a924B01a20642aF2460d7Fe24A2FEf89074d", "proxy-ynLSDe": "0x35Ec69A77B79c255e5d47D5A3BdbEFEfE342630c", "proxy-assetRegistry": "0x323C933df2523D5b0C756210446eeE0fB84270fd", "proxy-eigenStrategyManager": "0x92D904019A92B0Cafce3492Abb95577C285A68fC", @@ -25,6 +28,9 @@ "proxy-tokenStakingNodesManager": "0x6B566CB6cDdf7d140C59F84594756a151030a0C3", "proxy-ynEigenDepositAdapter": "0x9e72155d301a6555dc565315be72D295c76753c0", "proxy-ynEigenViewer": "0x9B933D84Fac0782F3B275D76B64a0DBf6FBEf28F", + "proxy-redemptionAssetsVault": "0x73bC33999C34a5126CA19dC900F22690C288D55e", + "proxy-withdrawalQueueManager": "0x8Face3283E20b19d98a7a132274B69C1304D60b4", + "proxy-wrapper": "0x99dB7619C018D61dBC2822767B63240d311d6992", "proxyAdmin-ynLSDe": "0x1bfF798A6072597c401f7C83A6a1096Ae5F0aFf7", "proxyAdmin-assetRegistry": "0xDf92BE359fB53846cCdaC8FFF1884314533949C7", "proxyAdmin-eigenStrategyManager": "0x69C34FB00Ebc0d7ac09Ab7968D2Eb9a07C2eB301", @@ -32,6 +38,9 @@ "proxyAdmin-tokenStakingNodesManager": "0x850d012115fb4D90711F53e86B2945019Bf7F36C", "proxyAdmin-ynEigenDepositAdapter": "0x7D779806B0c6A0201984b82e57830B84a75c3C07", "proxyAdmin-ynEigenViewer": "0x40fBdD124e80fF168574Fa7823440E574345307E", - "tokenStakingNodeImplementation": "0x57e1D090B1aF526CD4174019D5b9702EEBE236FA", + "proxyAdmin-redemptionAssetsVault": "0xE5E91680FE69F508B92bdCBCA2f867baAF58BAbB", + "proxyAdmin-withdrawalQueueManager": "0xe612764D1986693f46e99605d274Bbe28c3F03a7", + "proxyAdmin-wrapper": "0x151057A14a4c84403e77C1fbc4f22a8156f63A4B", + "tokenStakingNodeImplementation": "0xc602682b9ebc9719181b7a2b2479291cba26f801", "upgradeTimelock": "0xbB73f8a5B0074b27c6df026c77fA08B0111D017A" -} \ No newline at end of file +} diff --git a/deployments/YnLSDe-17000.json b/deployments/YnLSDe-17000.json index 3fcdb41e6..e060149a6 100644 --- a/deployments/YnLSDe-17000.json +++ b/deployments/YnLSDe-17000.json @@ -11,13 +11,16 @@ "UNPAUSE_ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", "YNDev": "0x9Dd8F69b62ddFd990241530F47dcEd0Dad7f7d39", "YnSecurityCouncil": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", - "implementation-ynLSDe": "0x92Df7b6001EF4cFe40B6b425bC4a358c05f27624", - "implementation-assetRegistry": "0x7385f1dBF3b0Ee3d85c89A38901Aa87333D30946", - "implementation-eigenStrategyManager": "0xc599064e66FB509FD49B5083896649a742066758", + "implementation-ynLSDe": "0x350793a4B8F19Ae1a67E5b4F3646483847CB7550", + "implementation-assetRegistry": "0xB8d77186574BB4951C20464DBBfB31C6b018c4B0", + "implementation-eigenStrategyManager": "0x0B02f50fB5c498eB63231f65844B88763b91C5C9", "implementation-rateProvider": "0x0Ca50907B8B5fDc6b0B1d5F23195209aD0457113", - "implementation-tokenStakingNodesManager": "0xAD89Fd40BE78811E279C89FF15DC3B831785192D", - "implementation-ynEigenDepositAdapter": "0x7af5cc12cee35dee9ccd0aa4d5e1772eb45b2046", + "implementation-tokenStakingNodesManager": "0x3E07B130533A8D3285203c697d6ff2b25996397B", + "implementation-ynEigenDepositAdapter": "0x9E12251f0A7728d6804Aba297a7CE725C4B77e4c", "implementation-ynEigenViewer": "0x85bB85b81Db2f9b446e9100057420AE5DE7232E4", + "implementation-redemptionAssetsVault": "0x398e9AE08179E2e07dDD51C7DCB9d585F3abC31A", + "implementation-withdrawalQueueManager": "0xf1B38e1ef304dE9a289219DCA7350f8cEE36C509", + "implementation-wrapper": "0xAd13B029FaF660a45b6F81888bB2fd1EF235Ef30", "proxy-ynLSDe": "0x071bdC8eDcdD66730f45a3D3A6F794FAA37C75ED", "proxy-assetRegistry": "0xaD31546AdbfE1EcD7137310508f112039a35b6F7", "proxy-eigenStrategyManager": "0xA0a11A9b84bf87c0323bc183715a22eC7881B7FC", @@ -25,6 +28,9 @@ "proxy-tokenStakingNodesManager": "0x5c20D1a85C7d9acB503135a498E26Eb55d806552", "proxy-ynEigenDepositAdapter": "0x7d0c1F604571a1c015684e6c15f2DdEc432C5e74", "proxy-ynEigenViewer": "0xECCE549926637E974Ca5739a8827E612682415E7", + "proxy-redemptionAssetsVault": "0xd536087701fFf805d20ee6651E55C90D645fD1a3", + "proxy-withdrawalQueueManager": "0xaF8052DC454318D52A4478a91aCa14305590389f", + "proxy-wrapper": "0x8F61bcb28C5b88e5F10ec5bb3C18f231D763A309", "proxyAdmin-ynLSDe": "0x31456Eef519b7ab236e3638297Ed392390bf304F", "proxyAdmin-assetRegistry": "0x4248392db8Ee31aA579822207d059A28A38c4510", "proxyAdmin-eigenStrategyManager": "0x010c60d663fddDAA076F0cE63f6692f0b5605fE5", @@ -32,6 +38,9 @@ "proxyAdmin-tokenStakingNodesManager": "0x18ED5129bCEfA996B4cade4e614c8941De3126d2", "proxyAdmin-ynEigenDepositAdapter": "0x9E9ce6D0fD72c7A31Eb7D99d8eCEA4b35a4FD088", "proxyAdmin-ynEigenViewer": "0x4879936e5822b936A9981f8F67844BC77096d433", - "tokenStakingNodeImplementation": "0xd1436C90205Dc2F807C33D88F122dC9D06964200", + "proxyAdmin-redemptionAssetsVault": "0x9885975Dd0b7425fE261C85197C3fd511eA6387C", + "proxyAdmin-withdrawalQueueManager": "0xa4BC4Ac496BEf4E652AD518C25a70F1797BF7620", + "proxyAdmin-wrapper": "0x47963bcB8d4d2faB0fc600E2c4B3151b917BF4b1", + "tokenStakingNodeImplementation": "0x4486c96883ee436525e11cfb1b0f589c11ff75C6", "upgradeTimelock": "0x62173555C27C67644C5634e114e42A63A59CD7A5" } \ No newline at end of file diff --git a/deployments/v0.0.2-ynEigenWithdrawals.json b/deployments/v0.0.2-ynEigenWithdrawals.json new file mode 100644 index 000000000..780aae0e0 --- /dev/null +++ b/deployments/v0.0.2-ynEigenWithdrawals.json @@ -0,0 +1,949 @@ +{ + "transactions": [ + { + "hash": "0x2febb0d22e189b6811f6ec5dc29462aed67c28db02adb663b6a2efa58cbbf022", + "transactionType": "CREATE", + "contractName": "RedemptionAssetsVault", + "contractAddress": "0x9892a40fe6e17d4c88a92b2e37c12981baa6f14a", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x22f93c", + "value": "0x0", + "input": "0x608060405234801561000f575f80fd5b5061001861001d565b6100cf565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006d5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cc5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b611e68806100dc5f395ff3fe608060405234801561000f575f80fd5b5060043610610153575f3560e01c80638456cb59116100bf578063ae648e9011610079578063ae648e90146102be578063d2edb68f146102df578063d547741f146102f2578063e0c784a614610305578063e63ab1e914610325578063fb1bb9de1461034c575f80fd5b80638456cb591461026f57806391d1485414610277578063979d7e861461028a5780639a2be4af1461029d578063a217fddf146102af578063acd08aa7146102b6575f80fd5b806336568abe1161011057806336568abe146102125780633f4ba83a14610225578063540385a31461022d5780635c62c822146102355780635c975abb146102485780636e553f651461025c575f80fd5b806301ffc9a7146101575780630415cc151461017f578063248a9ca31461019457806327e235e3146101b55780632ba29d38146101d45780632f2ff15d146101ff575b5f80fd5b61016a6101653660046119ba565b610373565b60405190151581526020015b60405180910390f35b61019261018d366004611a41565b6103a9565b005b6101a76101a2366004611ac4565b610629565b604051908152602001610176565b6101a76101c3366004611adb565b60036020525f908152604090205481565b6002546101e7906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b61019261020d366004611af6565b610649565b610192610220366004611af6565b61066b565b6101926106a3565b6101a761072f565b610192610243366004611ac4565b6107a6565b60015461016a90600160a01b900460ff1681565b61019261026a366004611af6565b610bde565b610192610ced565b61016a610285366004611af6565b610d80565b6001546101e7906001600160a01b031681565b5f546101e7906001600160a01b031681565b6101a75f81565b6101a7610db6565b6102d16102cc366004611ac4565b610f0e565b604051610176929190611b5e565b6101926102ed366004611bbe565b6111c2565b610192610300366004611af6565b6115bb565b610318610313366004611c40565b6115d7565b6040516101769190611caf565b6101a77f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6101a77f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a81565b5f6001600160e01b03198216637965db0b60e01b14806103a357506301ffc9a760e01b6001600160e01b03198316145b92915050565b80516001600160a01b0381166103d25760405163d92e233d60e01b815260040160405180910390fd5b60208201516001600160a01b0381166103fe5760405163d92e233d60e01b815260040160405180910390fd5b60408301516001600160a01b03811661042a5760405163d92e233d60e01b815260040160405180910390fd5b60608401516001600160a01b0381166104565760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f8115801561049b5750825b90505f8267ffffffffffffffff1660011480156104b75750303b155b9050811580156104c5575080155b156104e35760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561050d57845460ff60401b1916600160401b1785555b6105156116a0565b61051d6116aa565b895161052a905f906116ba565b506105587f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8b5f01516116ba565b506105867f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a8b5f01516116ba565b5060208a0151600280546001600160a01b039283166001600160a01b03199182161790915560408c01515f80549184169190921617905560608b0151600180546001600160a81b03191691909216179055831561061d57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b5f9081525f80516020611df3833981519152602052604090206001015490565b61065282610629565b61065b8161175b565b61066583836116ba565b50505050565b6001600160a01b03811633146106945760405163334bd91960e11b815260040160405180910390fd5b61069e8282611765565b505050565b7f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a6106cd8161175b565b600154600160a01b900460ff166106f757604051630e5e3b3f60e01b815260040160405180910390fd5b6001805460ff60a01b191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a150565b5f805460405163266d6a8360e11b8152670de0b6b3a764000060048201526001600160a01b0390911690634cdad50690602401602060405180830381865afa15801561077d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107a19190611cc1565b905090565b6002546001600160a01b031633146107d857604051630bde7ac360e11b81523360048201526024015b60405180910390fd5b600154600160a01b900460ff16156108035760405163ab35696f60e01b815260040160405180910390fd5b61080b6117de565b600154604080516319f92b0b60e21b815290515f926001600160a01b0316916367e4ac2c91600480830192869291908290030181865afa158015610851573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108789190810190611cd8565b90505f5b8151811015610b6a575f82828151811061089857610898611d85565b6020908102919091018101516001600160a01b0381165f90815260039092526040909120549091508015610b6057600154604051631cbf960d60e01b81526001600160a01b038481166004830152602482018490525f921690631cbf960d90604401602060405180830381865afa158015610915573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109399190611cc1565b9050858110610a935760015460405163833eaaf560e01b81526001600160a01b038581166004830152602482018990525f92169063833eaaf590604401602060405180830381865afa158015610991573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b59190611cc1565b5f546040516336200dcf60e11b8152600481018390526001600160a01b038781166024830152929350911690636c401b9e906044015f604051808303815f87803b158015610a01575f80fd5b505af1158015610a13573d5f803e3d5ffd5b505050506001600160a01b0384165f9081526003602052604081208054839290610a3e908490611dad565b90915550505f546040518281526001600160a01b03918216913391908716907f10964f2d145c29d7c7688147486387f37f033564029b447ab7c0983f292acc789060200160405180910390a450505050610b6a565b5f546040516336200dcf60e11b8152600481018490526001600160a01b03858116602483015290911690636c401b9e906044015f604051808303815f87803b158015610add575f80fd5b505af1158015610aef573d5f803e3d5ffd5b5050506001600160a01b0384165f9081526003602052604081205550610b158187611dad565b5f546040518481529197506001600160a01b039081169133918616907f10964f2d145c29d7c7688147486387f37f033564029b447ab7c0983f292acc789060200160405180910390a4505b505060010161087c565b505f546040518381526001600160a01b0390911690339073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee907f125c22256a0038dbde3a7faa557f73d7103c42d8f7e805cebe674b24d894d48c9060200160405180910390a450610bdb60015f80516020611e1383398151915255565b50565b600154604051632fa657a360e11b81526001600160a01b03838116600483015290911690635f4caf4690602401602060405180830381865afa158015610c26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c4a9190611dc0565b610c675760405163981a2a2b60e01b815260040160405180910390fd5b6001600160a01b0381165f9081526003602052604081208054849290610c8e908490611ddf565b90915550610ca990506001600160a01b038216333085611828565b60405182815233906001600160a01b038316907f01527be533d184d44e3111afa7800fa60ced6e1b44bd025f8b457deb8ce0ce359060200160405180910390a35050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d178161175b565b600154600160a01b900460ff1615610d425760405163ab35696f60e01b815260040160405180910390fd5b6001805460ff60a01b1916600160a01b1790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a150565b5f9182525f80516020611df3833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8060015f9054906101000a90046001600160a01b03166001600160a01b03166367e4ac2c6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e07573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e2e9190810190611cd8565b80519091505f5b81811015610f08575f838281518110610e5057610e50611d85565b6020908102919091018101516001600160a01b0381165f90815260039092526040909120549091508015610efe57600154604051631cbf960d60e01b81526001600160a01b0384811660048301526024820184905290911690631cbf960d90604401602060405180830381865afa158015610ecd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef19190611cc1565b610efb9087611ddf565b95505b5050600101610e35565b50505090565b6060805f610f1a610db6565b905083811015610f615760405163a8c6953f60e01b815273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee600482015260248101859052604481018290526064016107cf565b60015f9054906101000a90046001600160a01b03166001600160a01b03166367e4ac2c6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610fb0573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610fd79190810190611cd8565b9250825167ffffffffffffffff811115610ff357610ff36119e8565b60405190808252806020026020018201604052801561101c578160200160208202803683370190505b5091505f5b83518110156111bb575f84828151811061103d5761103d611d85565b6020908102919091018101516001600160a01b0381165f908152600390925260409091205490915080156111b157600154604051631cbf960d60e01b81526001600160a01b038481166004830152602482018490525f921690631cbf960d90604401602060405180830381865afa1580156110ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110de9190611cc1565b90508781106111845760015460405163833eaaf560e01b81526001600160a01b038581166004830152602482018b90525f92169063833eaaf590604401602060405180830381865afa158015611136573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061115a9190611cc1565b90508087868151811061116f5761116f611d85565b602002602001018181525050505050506111bb565b61118e8189611dad565b9750818685815181106111a3576111a3611d85565b602002602001018181525050505b5050600101611021565b5050915091565b6002546001600160a01b031633146111ef57604051630bde7ac360e11b81523360048201526024016107cf565b600154600160a01b900460ff161561121a5760405163ab35696f60e01b815260040160405180910390fd5b6112226117de565b5f61122b610db6565b9050838110156112725760405163a8c6953f60e01b815273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee600482015260248101859052604481018290526064016107cf565b600154604080516319f92b0b60e21b8152905186925f926001600160a01b03909116916367e4ac2c9160048082019286929091908290030181865afa1580156112bd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112e49190810190611cd8565b90505f5b815181101561154b575f82828151811061130457611304611d85565b6020908102919091018101516001600160a01b0381165f9081526003909252604090912054909150801561154157600154604051631cbf960d60e01b81526001600160a01b038481166004830152602482018490525f921690631cbf960d90604401602060405180830381865afa158015611381573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113a59190611cc1565b90508981106114b05760015460405163833eaaf560e01b81526001600160a01b038581166004830152602482018d90525f92169063833eaaf590604401602060405180830381865afa1580156113fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114219190611cc1565b90506114376001600160a01b0385168d8361188f565b6001600160a01b0384165f908152600360205260408120805483929061145e908490611dad565b90915550506040518181526001600160a01b03808e169133918716907f25137ec1c481240ec1a0e55c3c8c5f5e3467c1a66454f84fb39c963378cc0e779060200160405180910390a45050505061154b565b6114c46001600160a01b0384168c8461188f565b6001600160a01b0383165f908152600360205260408120556114e6818b611dad565b99508a6001600160a01b0316336001600160a01b0316846001600160a01b03167f25137ec1c481240ec1a0e55c3c8c5f5e3467c1a66454f84fb39c963378cc0e778560405161153791815260200190565b60405180910390a4505b50506001016112e8565b506040518281526001600160a01b03881690339073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee907f125c22256a0038dbde3a7faa557f73d7103c42d8f7e805cebe674b24d894d48c9060200160405180910390a450505061066560015f80516020611e1383398151915255565b6115c482610629565b6115cd8161175b565b6106658383611765565b6060818067ffffffffffffffff8111156115f3576115f36119e8565b60405190808252806020026020018201604052801561161c578160200160208202803683370190505b5091505f5b818110156116985760035f86868481811061163e5761163e611d85565b90506020020160208101906116539190611adb565b6001600160a01b03166001600160a01b031681526020019081526020015f205483828151811061168557611685611d85565b6020908102919091010152600101611621565b505092915050565b6116a86118c0565b565b6116b26118c0565b6116a8611909565b5f5f80516020611df38339815191526116d38484610d80565b611752575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556117083390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019150506103a3565b5f9150506103a3565b610bdb8133611911565b5f5f80516020611df383398151915261177e8484610d80565b15611752575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a460019150506103a3565b5f80516020611e1383398151915280546001190161180f57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b60015f80516020611e1383398151915255565b6040516001600160a01b0384811660248301528381166044830152606482018390526106659186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061194e565b6040516001600160a01b0383811660248301526044820183905261069e91859182169063a9059cbb9060640161185d565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166116a857604051631afcd79f60e31b815260040160405180910390fd5b6118156118c0565b61191b8282610d80565b61194a5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016107cf565b5050565b5f8060205f8451602086015f885af18061196d576040513d5f823e3d81fd5b50505f513d91508115611984578060011415611991565b6001600160a01b0384163b155b1561066557604051635274afe760e01b81526001600160a01b03851660048201526024016107cf565b5f602082840312156119ca575f80fd5b81356001600160e01b0319811681146119e1575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611a2557611a256119e8565b604052919050565b6001600160a01b0381168114610bdb575f80fd5b5f60808284031215611a51575f80fd5b6040516080810181811067ffffffffffffffff82111715611a7457611a746119e8565b6040528235611a8281611a2d565b81526020830135611a9281611a2d565b60208201526040830135611aa581611a2d565b60408201526060830135611ab881611a2d565b60608201529392505050565b5f60208284031215611ad4575f80fd5b5035919050565b5f60208284031215611aeb575f80fd5b81356119e181611a2d565b5f8060408385031215611b07575f80fd5b823591506020830135611b1981611a2d565b809150509250929050565b5f815180845260208085019450602084015f5b83811015611b5357815187529582019590820190600101611b37565b509495945050505050565b604080825283519082018190525f906020906060840190828701845b82811015611b9f5781516001600160a01b031684529284019290840190600101611b7a565b5050508381036020850152611bb48186611b24565b9695505050505050565b5f805f8060608587031215611bd1575f80fd5b8435611bdc81611a2d565b935060208501359250604085013567ffffffffffffffff80821115611bff575f80fd5b818701915087601f830112611c12575f80fd5b813581811115611c20575f80fd5b886020828501011115611c31575f80fd5b95989497505060200194505050565b5f8060208385031215611c51575f80fd5b823567ffffffffffffffff80821115611c68575f80fd5b818501915085601f830112611c7b575f80fd5b813581811115611c89575f80fd5b8660208260051b8501011115611c9d575f80fd5b60209290920196919550909350505050565b602081525f6119e16020830184611b24565b5f60208284031215611cd1575f80fd5b5051919050565b5f6020808385031215611ce9575f80fd5b825167ffffffffffffffff80821115611d00575f80fd5b818501915085601f830112611d13575f80fd5b815181811115611d2557611d256119e8565b8060051b9150611d368483016119fc565b8181529183018401918481019088841115611d4f575f80fd5b938501935b83851015611d795784519250611d6983611a2d565b8282529385019390850190611d54565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156103a3576103a3611d99565b5f60208284031215611dd0575f80fd5b815180151581146119e1575f80fd5b808201808211156103a3576103a3611d9956fe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220955d052416e979b79524e8e445f4d6f5f968cad3825b3dd1a7e594bd544a078564736f6c63430008180033", + "nonce": "0xe0", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x66605fc4a78e1077605cce6d40694b602e195111db7d77976ea4de3072174ee8", + "transactionType": "CREATE", + "contractName": "TransparentUpgradeableProxy", + "contractAddress": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "function": null, + "arguments": [ + "0x9892A40FE6e17d4C88a92b2e37c12981bAA6F14A", + "0xbB73f8a5B0074b27c6df026c77fA08B0111D017A", + "0x" + ], + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0xce728", + "value": "0x0", + "input": "0x60a060405260405162000e5038038062000e508339810160408190526200002691620003bc565b828162000034828262000099565b50508160405162000045906200035a565b6001600160a01b039091168152602001604051809103905ff0801580156200006f573d5f803e3d5ffd5b506001600160a01b0316608052620000906200008a60805190565b620000fe565b505050620004b3565b620000a4826200016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000f057620000eb8282620001ee565b505050565b620000fa62000267565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200013f5f8051602062000e30833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a16200016c8162000289565b50565b806001600160a01b03163b5f03620001aa57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516200020c919062000496565b5f60405180830381855af49150503d805f811462000246576040519150601f19603f3d011682016040523d82523d5f602084013e6200024b565b606091505b5090925090506200025e858383620002ca565b95945050505050565b3415620002875760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002b457604051633173bdd160e11b81525f6004820152602401620001a1565b805f8051602062000e30833981519152620001cd565b606082620002e357620002dd8262000330565b62000329565b8151158015620002fb57506001600160a01b0384163b155b156200032657604051639996b31560e01b81526001600160a01b0385166004820152602401620001a1565b50805b9392505050565b805115620003415780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6104fc806200093483390190565b80516001600160a01b03811681146200037f575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015620003b45781810151838201526020016200039a565b50505f910152565b5f805f60608486031215620003cf575f80fd5b620003da8462000368565b9250620003ea6020850162000368565b60408501519092506001600160401b038082111562000407575f80fd5b818601915086601f8301126200041b575f80fd5b81518181111562000430576200043062000384565b604051601f8201601f19908116603f011681019083821181831017156200045b576200045b62000384565b8160405282815289602084870101111562000474575f80fd5b6200048783602083016020880162000398565b80955050505050509250925092565b5f8251620004a981846020870162000398565b9190910192915050565b608051610469620004cb5f395f601001526104695ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102069190610407565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff80821115610381575f80fd5b818501915085601f830112610394575f80fd5b8135818111156103a6576103a661032a565b604051601f8201601f19908116603f011681019083821181831017156103ce576103ce61032a565b816040528281528860208487010111156103e6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610426576020818601810151858301520161040c565b505f92019182525091905056fea264697066735822122055a96d9f6d94a6ea50b308b2fc4aa0566df833e7551386bf651c4f24b0cc8f0a64736f6c63430008180033608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61030000000000000000000000009892a40fe6e17d4c88a92b2e37c12981baa6f14a000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0xe1", + "chainId": "0x1" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0xe5e91680fe69f508b92bdcbca2f867baaf58babb", + "initCode": "0x608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0xf6efd462bd99ad0841bcb0087ad440853c97da045dbe90f8d911605a3a0354a2", + "transactionType": "CREATE", + "contractName": "WithdrawalQueueManager", + "contractAddress": "0xaac93a4dde34ce9ad9dd8556b9fadd83380a5d64", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x475d45", + "value": "0x0", + "input": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000d5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d25780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b613f8b80620000e35f395ff3fe608060405234801561000f575f80fd5b5060043610610388575f3560e01c80637d1f8a81116101df578063ac1e502511610109578063dbbfd152116100a9578063e6dc4f1611610079578063e6dc4f1614610824578063e985e9c514610837578063efdcd9741461084a578063f84694e11461085d575f80fd5b8063dbbfd152146107f6578063e26dc432146107fe578063e51aa67814610811578063e63a391f1461081a575f80fd5b8063b88d4fde116100e4578063b88d4fde14610771578063bbeea20b14610784578063c87b56dd146107d0578063d547741f146107e3575f80fd5b8063ac1e502514610743578063b3f0067414610756578063b6dddc8314610769575f80fd5b80639c69c3471161017f578063a08ab5c31161014f578063a08ab5c314610702578063a217fddf14610715578063a22cb4651461071c578063aae733581461072f575f80fd5b80639c69c347146106a25780639dea569d146106b55780639ee679e8146106c8578063a024d723146106db575f80fd5b80638c4724cc116101ba5780638c4724cc1461065a57806391d1485414610662578063937b25811461067557806395d89b411461069a575f80fd5b80637d1f8a811461063557806384c4bd4b146106485780638bc7e8c414610651575f80fd5b80632f745c59116102c05780634718d52711610260578063612c1fa011610230578063612c1fa0146105d65780636352211e146105fd57806370a0823114610610578063748f9ef014610623575f80fd5b80634718d527146105405780634bac05a9146105825780634f6ccce7146105a35780635209cb98146105b6575f80fd5b80633569d58a1161029b5780633569d58a1461050757806336568abe146105105780633dd31e0e1461052357806342842e0e1461052d575f80fd5b80632f745c59146104ce5780633384d9fb146104e157806334e73122146104f4575f80fd5b80630b7019d91161032b57806318160ddd1161030657806318160ddd1461048157806323b872dd14610495578063248a9ca3146104a85780632f2ff15d146104bb575f80fd5b80630b7019d9146104445780630cc2250f1461045b578063115949211461046e575f80fd5b80630770fa91116103665780630770fa91146103de578063081812fc146103f35780630913b1211461041e578063095ea7b314610431575f80fd5b806301ffc9a71461038c57806306fdde03146103b4578063071fc512146103c9575b5f80fd5b61039f61039a366004613384565b610870565b60405190151581526020015b60405180910390f35b6103bc61089a565b6040516103ab91906133ec565b61039f6103d73660046133fe565b6009541190565b6103f16103ec3660046133fe565b61093b565b005b6104066104013660046133fe565b610a38565b6040516001600160a01b0390911681526020016103ab565b6103f161042c36600461345c565b610a4c565b6103f161043f3660046134e1565b610ad2565b61044d60045481565b6040519081526020016103ab565b6103f16104693660046135d0565b610ae1565b6103f161047c3660046136e4565b610df2565b5f80516020613ed68339815191525461044d565b6103f16104a3366004613743565b610e1c565b61044d6104b63660046133fe565b610ea5565b6103f16104c9366004613781565b610ec5565b61044d6104dc3660046134e1565b610ee1565b6103f16104ef366004613781565b610f52565b61044d6105023660046137af565b610fa9565b61044d60095481565b6103f161051e366004613781565b610fc9565b61044d6224ea0081565b6103f161053b366004613743565b611001565b61055361054e3660046133fe565b61101b565b604080516001600160401b0394851681529390921660208401526001600160601b0316908201526060016103ab565b6105956105903660046137cf565b61105e565b6040516103ab929190613832565b61044d6105b13660046133fe565b611294565b6105c96105c43660046133fe565b611306565b6040516103ab91906138c8565b61044d7f16e47d7ccdc4d9916471674b101198c830d9d6666d46998629b3ca840510386e81565b61040661060b3660046133fe565b611427565b61044d61061e3660046137cf565b611431565b5f54610406906001600160a01b031681565b600154610406906001600160a01b031681565b61044d60025481565b61044d60055481565b61044d611489565b61039f610670366004613781565b611526565b6106886106833660046133fe565b61155c565b6040516103ab969594939291906138da565b6103bc61161f565b61044d6106b03660046137af565b61165d565b600754610406906001600160a01b031681565b61044d6106d63660046133fe565b6116e6565b61044d7f8586893ec6c8c067a87b0dc34e01d210b44bbdce9d41cb027cc2d7c0f31ead9581565b61044d610710366004613918565b6116fb565b61044d5f81565b6103f161072a36600461395b565b6118cb565b61044d5f80516020613f3683398151915281565b6103f16107513660046133fe565b6118d6565b600654610406906001600160a01b031681565b600a5461044d565b6103f161077f36600461398b565b61194d565b6107976107923660046133fe565b611965565b6040805182516001600160401b03908116825260208085015190911690820152918101516001600160601b0316908201526060016103ab565b6103bc6107de3660046133fe565b611a0b565b6103f16107f1366004613781565b611a7b565b61044d611a97565b6103f161080c3660046139f2565b611b26565b61044d60085481565b61044d620f424081565b61044d6108323660046133fe565b611b6d565b61039f610845366004613a60565b611da5565b6103f16108583660046137cf565b611df1565b61044d61086b3660046133fe565b611e8d565b5f6001600160e01b031982166380ac58cd60e01b1480610894575061089482611fc6565b92915050565b5f80516020613eb683398151915280546060919081906108b990613a8c565b80601f01602080910402602001604051908101604052809291908181526020018280546108e590613a8c565b80156109305780601f1061090757610100808354040283529160200191610930565b820191905f5260205f20905b81548152906001019060200180831161091357829003601f168201915b505050505091505090565b7f16e47d7ccdc4d9916471674b101198c830d9d6666d46998629b3ca840510386e61096581611fea565b5f61096e611a97565b9050808311156109a057604051630bf0035360e31b815260048101849052602481018290526044015b60405180910390fd5b600154604051632e31641160e11b8152600481018590526001600160a01b0390911690635c62c822906024015f604051808303815f87803b1580156109e3575f80fd5b505af11580156109f5573d5f803e3d5ffd5b505060408051868152602081018590527f5471a21865bef29e2f9817eeb3138f749523b6e76a3c880a65fdd61d35604ac8935001905060405180910390a1505050565b5f610a4282611ff4565b506108948261202b565b828114610a7657604051631f4bb7c160e31b81526004810184905260248101829052604401610997565b5f5b83811015610acb57610ac3858583818110610a9557610a95613ac4565b90506020020135848484818110610aae57610aae613ac4565b90506020020160208101906104ef91906137cf565b600101610a78565b5050505050565b610add828233612064565b5050565b60808101516001600160a01b038116610b0d5760405163d92e233d60e01b815260040160405180910390fd5b60408201516001600160a01b038116610b395760405163d92e233d60e01b815260040160405180910390fd5b60608301516001600160a01b038116610b655760405163d92e233d60e01b815260040160405180910390fd5b60a08401516001600160a01b038116610b915760405163d92e233d60e01b815260040160405180910390fd5b6101008501516001600160a01b038116610bbe5760405163d92e233d60e01b815260040160405180910390fd5b6101208601516001600160a01b038116610beb5760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610c2f5750825b90505f826001600160401b03166001148015610c4a5750303b155b905081158015610c58575080155b15610c765760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610ca057845460ff60401b1916600160401b1785555b610cb18c5f01518d60200151612071565b60408c01515f80546001600160a01b039283166001600160a01b031991821617825560608f0151600180549190941691161790915560808d0151610cf59190612083565b50610d115f80516020613f368339815191528d60a00151612083565b50610d407f16e47d7ccdc4d9916471674b101198c830d9d6666d46998629b3ca840510386e8d60c00151612083565b50610d707f8586893ec6c8c067a87b0dc34e01d210b44bbdce9d41cb027cc2d7c0f31ead958d6101200151612083565b5060e08c01516005556101008c0151600680546001600160a01b0319166001600160a01b039092169190911790558315610de457845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b610dfa612124565b610e038161215b565b610e1960015f80516020613f1683398151915255565b50565b6001600160a01b038216610e4557604051633250574960e11b81525f6004820152602401610997565b5f610e518383336126c5565b9050836001600160a01b0316816001600160a01b031614610e9f576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610997565b50505050565b5f9081525f80516020613ef6833981519152602052604090206001015490565b610ece82610ea5565b610ed781611fea565b610e9f8383612083565b5f5f80516020613e96833981519152610ef984611431565b8310610f2a5760405163295f44f760e21b81526001600160a01b038516600482015260248101849052604401610997565b6001600160a01b0384165f908152602091825260408082208583529092522054905092915050565b610f5a612124565b5f6040518060600160405280848152602001610f7585611e8d565b8152602001836001600160a01b03168152509050610f928161215b565b50610add60015f80516020613f1683398151915255565b5f620f4240610fb88385613aec565b610fc29190613b03565b9392505050565b6001600160a01b0381163314610ff25760405163334bd91960e11b815260040160405180910390fd5b610ffc82826127c3565b505050565b610ffc83838360405180602001604052805f81525061194d565b600a818154811061102a575f80fd5b5f918252602090912001546001600160401b038082169250600160401b82041690600160801b90046001600160601b031683565b6060805f61106b84611431565b9050805f036110b757604080515f808252602082018181528284019093529091906110ac565b61109961333c565b8152602001906001900390816110915790505b509250925050915091565b806001600160401b038111156110cf576110cf61350b565b6040519080825280602002602001820160405280156110f8578160200160208202803683370190505b509250806001600160401b038111156111135761111361350b565b60405190808252806020026020018201604052801561114c57816020015b61113961333c565b8152602001906001900390816111315790505b5091505f5b8181101561128d575f6111648683610ee1565b90508085838151811061117957611179613ac4565b6020908102919091018101919091525f8281526003808352604091829020825160c081018452815481526001820154948101949094526002810154928401929092528101546060830152600481015460ff161515608083015260058101805460a0840191906111e790613a8c565b80601f016020809104026020016040519081016040528092919081815260200182805461121390613a8c565b801561125e5780601f106112355761010080835404028352916020019161125e565b820191905f5260205f20905b81548152906001019060200180831161124157829003601f168201915b50505050508152505084838151811061127957611279613ac4565b602090810291909101015250600101611151565b5050915091565b5f5f80516020613e968339815191526112b85f80516020613ed68339815191525490565b83106112e05760405163295f44f760e21b81525f600482015260248101849052604401610997565b8060020183815481106112f5576112f5613ac4565b905f5260205f200154915050919050565b61130e61333c565b5f82815260036020818152604092839020835160c08101855281548152600182015492810192909252600281015493820193909352908201546060820152600482015460ff161515608082015260058201805491929160a08401919061137390613a8c565b80601f016020809104026020016040519081016040528092919081815260200182805461139f90613a8c565b80156113ea5780601f106113c1576101008083540402835291602001916113ea565b820191905f5260205f20905b8154815290600101906020018083116113cd57829003601f168201915b50505050508152505090506114028160600151151590565b61142257604051630169130760e01b815260048101839052602401610997565b919050565b5f61089482611ff4565b5f5f80516020613eb68339815191526001600160a01b038316611469576040516322718ad960e21b81525f6004820152602401610997565b6001600160a01b039092165f908152600390920160205250604090205490565b5f8060015f9054906101000a90046001600160a01b03166001600160a01b031663acd08aa76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114ff9190613b22565b905080600854111561151f57806008546115199190613b39565b91505090565b5f91505090565b5f9182525f80516020613ef6833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b600360208190525f9182526040909120805460018201546002830154938301546004840154600585018054949693959394929360ff9092169261159e90613a8c565b80601f01602080910402602001604051908101604052809291908181526020018280546115ca90613a8c565b80156116155780601f106115ec57610100808354040283529160200191611615565b820191905f5260205f20905b8154815290600101906020018083116115f857829003601f168201915b5050505050905086565b7f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab007930180546060915f80516020613eb6833981519152916108b990613a8c565b5f805f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d19190613b4c565b6116dc90600a613c4c565b610fb88385613aec565b5f6108948260405180602001604052805f8152505b5f611704612124565b825f0361172457604051635e85ae7360e01b815260040160405180910390fd5b5f5461173b906001600160a01b031633308661283c565b6001546040805163540385a360e01b815290515f926001600160a01b03169163540385a39160048083019260209291908290030181865afa158015611782573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117a69190613b22565b600280549192505f6117b783613c5a565b909155506040805160c08101825286815260058054602080840191825283850187815242606086019081525f6080870181815260a088018d81528a83526003958690529890912087518155945160018601559151600285015551918301919091555160048201805460ff1916911515919091179055925193955090928392918201906118439082613cb6565b50905050611851858361165d565b60085f8282546118619190613d71565b9091555061187190503384612896565b336001600160a01b0316837f470a96c327e4382aa8e66bc975ce38a8e3eacb9c8e4d87d34e8dc4a853539de6836040516118ab91906138c8565b60405180910390a3505061089460015f80516020613f1683398151915255565b610add3383836128f7565b5f80516020613f368339815191526118ed81611fea565b620f4240821115611911576040516314afa02960e21b815260040160405180910390fd5b60058290556040518281527fe94edcc114da5287ecb30ee8aacf12e6c16b11b8583d7f9e477ab1616e33d53d9060200160405180910390a15050565b611958848484610e1c565b610e9f33858585856129a6565b604080516060810182525f8082526020820181905291810191909152600a5482106119a55760405162a6e6ff60e61b815260048101839052602401610997565b600a82815481106119b8576119b8613ac4565b5f9182526020918290206040805160608101825291909201546001600160401b038082168352600160401b820416938201939093526001600160601b03600160801b909304929092169082015292915050565b6060611a1682611ff4565b505f611a2c60408051602081019091525f815290565b90505f815111611a4a5760405180602001604052805f815250610fc2565b80611a5484612acd565b604051602001611a65929190613d84565b6040516020818303038152906040529392505050565b611a8482610ea5565b611a8d81611fea565b610e9f83836127c3565b5f8060015f9054906101000a90046001600160a01b03166001600160a01b031663acd08aa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b0d9190613b22565b905060085481111561151f576008546115199082613b39565b5f5b81811015610ffc575f838383818110611b4357611b43613ac4565b905060600201803603810190611b5991906136e4565b9050611b6481610df2565b50600101611b28565b5f7f8586893ec6c8c067a87b0dc34e01d210b44bbdce9d41cb027cc2d7c0f31ead95611b9881611fea565b6001546040805163540385a360e01b815290515f926001600160a01b03169163540385a39160048083019260209291908290030181865afa158015611bdf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c039190613b22565b90505f6040518060600160405280611c1c600954612b5c565b6001600160401b03168152602001611c3387612b5c565b6001600160401b03168152602001611c4a84612b95565b6001600160601b03908116909152600a80546001810182555f9190915282517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a88201805460208601516040870151909516600160801b026bffffffffffffffffffffffff60801b196001600160401b03968716600160401b026fffffffffffffffffffffffffffffffff199093169690941695909517179190911692909217909155600254909550909150851115611d23576002546040516326af3c0960e21b8152610997918791600401918252602082015260400190565b6009548511611d535760095460405163b6c78a0360e01b8152610997918791600401918252602082015260400190565b600954604080518781526020810192909252810183905284907fec80db79f7dde8aa35235328c05a056f900bc38a0eb09fe40868458bef7963a09060600160405180910390a250505060099190915590565b6001600160a01b039182165f9081527f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab00793056020908152604080832093909416825291909152205460ff1690565b806001600160a01b038116611e195760405163d92e233d60e01b815260040160405180910390fd5b5f80516020613f36833981519152611e3081611fea565b6006546040516001600160a01b038086169216907fa92ff4390fe6943f0b30e8fe715dde86f85ab79b2b2c640a10fc094cc4036cc8905f90a35050600680546001600160a01b0319166001600160a01b0392909216919091179055565b600a545f90808203611eb557604051635f5010c560e11b815260048101849052602401610997565b5f80611ec2600184613b39565b90505b808211611faa575f6002611ed98385613d71565b611ee39190613b03565b90505f600a8281548110611ef957611ef9613ac4565b5f9182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160601b03169082015291508710801590611f62575080602001516001600160401b031687105b15611f71575095945050505050565b80516001600160401b0316871015611f9557611f8e600183613b39565b9250611fa3565b611fa0826001613d71565b93505b5050611ec5565b604051635f5010c560e11b815260048101869052602401610997565b5f6001600160e01b03198216637965db0b60e01b1480610894575061089482612bc8565b610e198133612bec565b5f80611fff83612c25565b90506001600160a01b03811661089457604051637e27328960e01b815260048101849052602401610997565b5f9081527f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab007930460205260409020546001600160a01b031690565b610ffc8383836001612c5e565b612079612d71565b610add8282612dbc565b5f5f80516020613ef683398151915261209c8484611526565b61211b575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556120d13390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610894565b5f915050610894565b5f80516020613f1683398151915280546001190161215557604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b8051602082015160408301513361217184612c25565b6001600160a01b03161415801561219c5750835133906121909061202b565b6001600160a01b031614155b156121c6578351604051636a931be560e11b81526004810191909152336024820152604401610997565b600a5482106121ea5760405162a6e6ff60e61b815260048101839052602401610997565b5f600a83815481106121fe576121fe613ac4565b5f9182526020918290206040805160608101825292909101546001600160401b03808216808552600160401b830490911694840194909452600160801b90046001600160601b0316908201529150841080612266575080602001516001600160401b03168410155b156122ac578051602082015160405163d0fca86360e01b815260048101879052602481018690526001600160401b03928316604482015291166064820152608401610997565b6040808201515f86815260036020818152848320855160c08101875281548152600182015492810192909252600281015495820195909552908401546060820152600484015460ff16151560808201526005840180546001600160601b0390941694929391929160a08401919061232290613a8c565b80601f016020809104026020016040519081016040528092919081815260200182805461234e90613a8c565b80156123995780601f1061237057610100808354040283529160200191612399565b820191905f5260205f20905b81548152906001019060200180831161237c57829003601f168201915b50505050508152505090506123b18160600151151590565b6123d157604051630169130760e01b815260048101879052602401610997565b8060800151156123f7576040516331d5519160e01b815260048101879052602401610997565b612402866009541190565b61242257604051635f5010c560e11b815260048101879052602401610997565b5f86815260036020526040808220600401805460ff19166001179055820151831161244d5782612453565b81604001515b90505f612463835f01518361165d565b90508060085f8282546124769190613b39565b90915550612485905088612dec565b5f548351604051630852cd8d60e31b81526001600160a01b03909216916342966c68916124b89160040190815260200190565b5f604051808303815f87803b1580156124cf575f80fd5b505af11580156124e1573d5f803e3d5ffd5b505050505f6124f4828560200151610fa9565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b031663acd08aa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612547573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061256b9190613b22565b9050828110156125985760405163cf47918160e01b81526004810182905260248101849052604401610997565b6001546001600160a01b031663d2edb68f896125b48587613b39565b8860a001516040518463ffffffff1660e01b81526004016125d793929190613db2565b5f604051808303815f87803b1580156125ee575f80fd5b505af1158015612600573d5f803e3d5ffd5b505050505f8211156126765760015460065460a087015160405163d2edb68f60e01b81526001600160a01b039384169363d2edb68f9361264893911691879190600401613db2565b5f604051808303815f87803b15801561265f575f80fd5b505af1158015612671573d5f803e3d5ffd5b505050505b897f043063fdf65eda59c2092782b3f6984485c435525b12b85fd117d2bd7e2d9a5c338a888d888a6040516126b096959493929190613de1565b60405180910390a25050505050505050505050565b5f806126d2858585612e24565b90506001600160a01b03811661275957612754845f80516020613ed683398151915280545f8381527f645e039705490088daad89bae25049a34f4a9072d398537b1ab2425f24cbed0360205260408120829055600182018355919091527fa42f15e5d656f8155fd7419d740a6073999f19cd6e061449ce4a257150545bf20155565b61277c565b846001600160a01b0316816001600160a01b03161461277c5761277c8185612f26565b6001600160a01b0385166127985761279384612fbd565b6127bb565b846001600160a01b0316816001600160a01b0316146127bb576127bb858561308a565b949350505050565b5f5f80516020613ef68339815191526127dc8484611526565b1561211b575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610894565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610e9f9085906130e2565b6001600160a01b0382166128bf57604051633250574960e11b81525f6004820152602401610997565b5f6128cb83835f6126c5565b90506001600160a01b03811615610ffc576040516339e3563760e11b81525f6004820152602401610997565b5f80516020613eb68339815191526001600160a01b03831661293757604051630b61174360e31b81526001600160a01b0384166004820152602401610997565b6001600160a01b038481165f818152600584016020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b6001600160a01b0383163b15610acb57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906129e8908890889087908790600401613e2a565b6020604051808303815f875af1925050508015612a22575060408051601f3d908101601f19168201909252612a1f91810190613e66565b60015b612a89573d808015612a4f576040519150601f19603f3d011682016040523d82523d5f602084013e612a54565b606091505b5080515f03612a8157604051633250574960e11b81526001600160a01b0385166004820152602401610997565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612ac557604051633250574960e11b81526001600160a01b0385166004820152602401610997565b505050505050565b60605f612ad98361314e565b60010190505f816001600160401b03811115612af757612af761350b565b6040519080825280601f01601f191660200182016040528015612b21576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612b2b57509392505050565b5f6001600160401b03821115612b9157604080516306dfcc6560e41b8152600481019190915260248101839052604401610997565b5090565b5f6001600160601b03821115612b91576040516306dfcc6560e41b81526060600482015260248101839052604401610997565b5f6001600160e01b0319821663780e9d6360e01b1480610894575061089482613225565b612bf68282611526565b610add5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610997565b5f9081527f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab007930260205260409020546001600160a01b031690565b5f80516020613eb68339815191528180612c8057506001600160a01b03831615155b15612d41575f612c8f85611ff4565b90506001600160a01b03841615801590612cbb5750836001600160a01b0316816001600160a01b031614155b8015612cce5750612ccc8185611da5565b155b15612cf75760405163a9fbf51f60e01b81526001600160a01b0385166004820152602401610997565b8215612d3f5784866001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5f93845260040160205250506040902080546001600160a01b0319166001600160a01b0392909216919091179055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16612dba57604051631afcd79f60e31b815260040160405180910390fd5b565b612dc4612d71565b5f80516020613eb683398151915280612ddd8482613cb6565b5060018101610e9f8382613cb6565b5f612df85f835f6126c5565b90506001600160a01b038116610add57604051637e27328960e01b815260048101839052602401610997565b5f5f80516020613eb683398151915281612e3d85612c25565b90506001600160a01b03841615612e5957612e59818587613274565b6001600160a01b03811615612e9557612e745f865f80612c5e565b6001600160a01b0381165f908152600383016020526040902080545f190190555b6001600160a01b03861615612ec5576001600160a01b0386165f9081526003830160205260409020805460010190555b5f85815260028301602052604080822080546001600160a01b0319166001600160a01b038a811691821790925591518893918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a495945050505050565b5f80516020613e968339815191525f612f3e84611431565b5f8481526001840160209081526040808320546001600160a01b03891684529186905290912091925090818314612f96575f838152602082815260408083205485845281842081905583526001870190915290208290555b5f948552600190930160209081526040808620869055928552929092528220919091555050565b5f80516020613ed6833981519152545f80516020613e96833981519152905f90612fe990600190613b39565b5f84815260038401602052604081205460028501805493945090928490811061301457613014613ac4565b905f5260205f20015490508084600201838154811061303557613035613ac4565b5f9182526020808320909101929092558281526003860190915260408082208490558682528120556002840180548061307057613070613e81565b600190038181905f5260205f20015f905590555050505050565b5f80516020613e968339815191525f60016130a485611431565b6130ae9190613b39565b6001600160a01b039094165f9081526020838152604080832087845282528083208690559482526001909301909252502055565b5f8060205f8451602086015f885af180613101576040513d5f823e3d81fd5b50505f513d91508115613118578060011415613125565b6001600160a01b0384163b155b15610e9f57604051635274afe760e01b81526001600160a01b0385166004820152602401610997565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061318c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106131b8576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106131d657662386f26fc10000830492506010015b6305f5e10083106131ee576305f5e100830492506008015b612710831061320257612710830492506004015b60648310613214576064830492506002015b600a83106108945760010192915050565b5f6001600160e01b031982166380ac58cd60e01b148061325557506001600160e01b03198216635b5e139f60e01b145b8061089457506301ffc9a760e01b6001600160e01b0319831614610894565b61327f8383836132d8565b610ffc576001600160a01b0383166132ad57604051637e27328960e01b815260048101829052602401610997565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610997565b5f6001600160a01b038316158015906127bb5750826001600160a01b0316846001600160a01b0316148061331157506133118484611da5565b806127bb5750826001600160a01b031661332a8361202b565b6001600160a01b031614949350505050565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f15158152602001606081525090565b6001600160e01b031981168114610e19575f80fd5b5f60208284031215613394575f80fd5b8135610fc28161336f565b5f5b838110156133b95781810151838201526020016133a1565b50505f910152565b5f81518084526133d881602086016020860161339f565b601f01601f19169290920160200192915050565b602081525f610fc260208301846133c1565b5f6020828403121561340e575f80fd5b5035919050565b5f8083601f840112613425575f80fd5b5081356001600160401b0381111561343b575f80fd5b6020830191508360208260051b8501011115613455575f80fd5b9250929050565b5f805f806040858703121561346f575f80fd5b84356001600160401b0380821115613485575f80fd5b61349188838901613415565b909650945060208701359150808211156134a9575f80fd5b506134b687828801613415565b95989497509550505050565b6001600160a01b0381168114610e19575f80fd5b8035611422816134c2565b5f80604083850312156134f2575f80fd5b82356134fd816134c2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b60405161014081016001600160401b03811182821017156135425761354261350b565b60405290565b5f82601f830112613557575f80fd5b81356001600160401b03808211156135715761357161350b565b604051601f8301601f19908116603f011681019082821181831017156135995761359961350b565b816040528381528660208588010111156135b1575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f602082840312156135e0575f80fd5b81356001600160401b03808211156135f6575f80fd5b90830190610140828603121561360a575f80fd5b61361261351f565b823582811115613620575f80fd5b61362c87828601613548565b825250602083013582811115613640575f80fd5b61364c87828601613548565b60208301525061365e604084016134d6565b604082015261366f606084016134d6565b6060820152613680608084016134d6565b608082015261369160a084016134d6565b60a08201526136a260c084016134d6565b60c082015260e083013560e082015261010091506136c18284016134d6565b8282015261012091506136d58284016134d6565b91810191909152949350505050565b5f606082840312156136f4575f80fd5b604051606081018181106001600160401b03821117156137165761371661350b565b806040525082358152602083013560208201526040830135613737816134c2565b60408201529392505050565b5f805f60608486031215613755575f80fd5b8335613760816134c2565b92506020840135613770816134c2565b929592945050506040919091013590565b5f8060408385031215613792575f80fd5b8235915060208301356137a4816134c2565b809150509250929050565b5f80604083850312156137c0575f80fd5b50508035926020909101359150565b5f602082840312156137df575f80fd5b8135610fc2816134c2565b805182526020810151602083015260408101516040830152606081015160608301526080810151151560808301525f60a082015160c060a08501526127bb60c08501826133c1565b604080825283519082018190525f906020906060840190828701845b8281101561386a5781518452928401929084019060010161384e565b50505083810382850152845180825282820190600581901b830184018785015f5b838110156138b957601f198684030185526138a78383516137ea565b9487019492509086019060010161388b565b50909998505050505050505050565b602081525f610fc260208301846137ea565b868152856020820152846040820152836060820152821515608082015260c060a08201525f61390c60c08301846133c1565b98975050505050505050565b5f8060408385031215613929575f80fd5b8235915060208301356001600160401b03811115613945575f80fd5b61395185828601613548565b9150509250929050565b5f806040838503121561396c575f80fd5b8235613977816134c2565b9150602083013580151581146137a4575f80fd5b5f805f806080858703121561399e575f80fd5b84356139a9816134c2565b935060208501356139b9816134c2565b92506040850135915060608501356001600160401b038111156139da575f80fd5b6139e687828801613548565b91505092959194509250565b5f8060208385031215613a03575f80fd5b82356001600160401b0380821115613a19575f80fd5b818501915085601f830112613a2c575f80fd5b813581811115613a3a575f80fd5b866020606083028501011115613a4e575f80fd5b60209290920196919550909350505050565b5f8060408385031215613a71575f80fd5b8235613a7c816134c2565b915060208301356137a4816134c2565b600181811c90821680613aa057607f821691505b602082108103613abe57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761089457610894613ad8565b5f82613b1d57634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215613b32575f80fd5b5051919050565b8181038181111561089457610894613ad8565b5f60208284031215613b5c575f80fd5b815160ff81168114610fc2575f80fd5b600181815b80851115613ba657815f1904821115613b8c57613b8c613ad8565b80851615613b9957918102915b93841c9390800290613b71565b509250929050565b5f82613bbc57506001610894565b81613bc857505f610894565b8160018114613bde5760028114613be857613c04565b6001915050610894565b60ff841115613bf957613bf9613ad8565b50506001821b610894565b5060208310610133831016604e8410600b8410161715613c27575081810a610894565b613c318383613b6c565b805f1904821115613c4457613c44613ad8565b029392505050565b5f610fc260ff841683613bae565b5f60018201613c6b57613c6b613ad8565b5060010190565b601f821115610ffc57805f5260205f20601f840160051c81016020851015613c975750805b601f840160051c820191505b81811015610acb575f8155600101613ca3565b81516001600160401b03811115613ccf57613ccf61350b565b613ce381613cdd8454613a8c565b84613c72565b602080601f831160018114613d16575f8415613cff5750858301515b5f19600386901b1c1916600185901b178555612ac5565b5f85815260208120601f198616915b82811015613d4457888601518255948401946001909101908401613d25565b5085821015613d6157878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561089457610894613ad8565b5f8351613d9581846020880161339f565b835190830190613da981836020880161339f565b01949350505050565b60018060a01b0384168152826020820152606060408201525f613dd860608301846133c1565b95945050505050565b6001600160a01b0387811682528616602082015260c0604082018190525f90613e0c908301876137ea565b606083019590955250608081019290925260a0909101529392505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90613e5c908301846133c1565b9695505050505050565b5f60208284031215613e76575f80fd5b8151610fc28161336f565b634e487b7160e01b5f52603160045260245ffdfe645e039705490088daad89bae25049a34f4a9072d398537b1ab2425f24cbed0080bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab0079300645e039705490088daad89bae25049a34f4a9072d398537b1ab2425f24cbed0202dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00947478cb7f25f91a774cb9fce49ddd1952e530220912f89fefb6a8e0d8f04381a264697066735822122094edb4d9f5a8cbd28e42a314088886a52a9369e17e8ac666e506d7587dafa74f64736f6c63430008180033", + "nonce": "0xe2", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa01662caef845b8b1812ffd5b114e679fe672a155c0e6fae8b9aa5d708c9a19a", + "transactionType": "CREATE", + "contractName": "TransparentUpgradeableProxy", + "contractAddress": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "function": null, + "arguments": [ + "0xaac93A4ddE34CE9ad9dD8556B9faDd83380a5D64", + "0xbB73f8a5B0074b27c6df026c77fA08B0111D017A", + "0x" + ], + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0xce728", + "value": "0x0", + "input": "0x60a060405260405162000e5038038062000e508339810160408190526200002691620003bc565b828162000034828262000099565b50508160405162000045906200035a565b6001600160a01b039091168152602001604051809103905ff0801580156200006f573d5f803e3d5ffd5b506001600160a01b0316608052620000906200008a60805190565b620000fe565b505050620004b3565b620000a4826200016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000f057620000eb8282620001ee565b505050565b620000fa62000267565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200013f5f8051602062000e30833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a16200016c8162000289565b50565b806001600160a01b03163b5f03620001aa57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516200020c919062000496565b5f60405180830381855af49150503d805f811462000246576040519150601f19603f3d011682016040523d82523d5f602084013e6200024b565b606091505b5090925090506200025e858383620002ca565b95945050505050565b3415620002875760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002b457604051633173bdd160e11b81525f6004820152602401620001a1565b805f8051602062000e30833981519152620001cd565b606082620002e357620002dd8262000330565b62000329565b8151158015620002fb57506001600160a01b0384163b155b156200032657604051639996b31560e01b81526001600160a01b0385166004820152602401620001a1565b50805b9392505050565b805115620003415780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6104fc806200093483390190565b80516001600160a01b03811681146200037f575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015620003b45781810151838201526020016200039a565b50505f910152565b5f805f60608486031215620003cf575f80fd5b620003da8462000368565b9250620003ea6020850162000368565b60408501519092506001600160401b038082111562000407575f80fd5b818601915086601f8301126200041b575f80fd5b81518181111562000430576200043062000384565b604051601f8201601f19908116603f011681019083821181831017156200045b576200045b62000384565b8160405282815289602084870101111562000474575f80fd5b6200048783602083016020880162000398565b80955050505050509250925092565b5f8251620004a981846020870162000398565b9190910192915050565b608051610469620004cb5f395f601001526104695ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102069190610407565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff80821115610381575f80fd5b818501915085601f830112610394575f80fd5b8135818111156103a6576103a661032a565b604051601f8201601f19908116603f011681019083821181831017156103ce576103ce61032a565b816040528281528860208487010111156103e6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610426576020818601810151858301520161040c565b505f92019182525091905056fea264697066735822122055a96d9f6d94a6ea50b308b2fc4aa0566df833e7551386bf651c4f24b0cc8f0a64736f6c63430008180033608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000aac93a4dde34ce9ad9dd8556b9fadd83380a5d64000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0xe3", + "chainId": "0x1" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0xe612764d1986693f46e99605d274bbe28c3f03a7", + "initCode": "0x608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x92cbba922a78a2716be9f9739eb33381a09f7d725479e5406319aaf367af02dd", + "transactionType": "CREATE", + "contractName": "LSDWrapper", + "contractAddress": "0x7c31a924b01a20642af2460d7fe24a2fef89074d", + "function": null, + "arguments": [ + "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", + "0xDcEe70654261AF21C44c093C300eD3Bb97b78192", + "0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3", + "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" + ], + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0xef42a", + "value": "0x0", + "input": "0x61010060405234801562000011575f80fd5b5060405162000f0138038062000f01833981016040819052620000349162000194565b6200003e620000c4565b6001600160a01b03841615806200005c57506001600160a01b038316155b806200006f57506001600160a01b038216155b806200008257506001600160a01b038116155b15620000a15760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0393841660805291831660a052821660c0521660e052620001ee565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620001155760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001755780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146200018f575f80fd5b919050565b5f805f8060808587031215620001a8575f80fd5b620001b38562000178565b9350620001c36020860162000178565b9250620001d36040860162000178565b9150620001e36060860162000178565b905092959194509250565b60805160a05160c05160e051610c31620002d05f395f8181610146015281816101b4015281816101f8015281816105420152818161056f015261074f01525f81816101020152818161030a0152818161034e0152818161066301526107a401525f818161016d015281816103920152818161040601528181610595015281816105ef015281816107c601528181610903015261095001525f818160c301528181610236015281816102b7015281816102e40152818161043f01528181610483015281816104c1015281816107710152818161083c01526108880152610c315ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80638129fc1c116100585780638129fc1c14610137578063c1fe3e4814610141578063daba667d14610168578063db7711c61461018f575f80fd5b806313bac820146100895780634aa07e64146100be5780634e6c9766146100fd5780637647691d14610124575b5f80fd5b61009c610097366004610b92565b6101b0565b604080519283526001600160a01b039091166020830152015b60405180910390f35b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b5565b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b61009c610132366004610b92565b61043b565b61013f61068b565b005b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b6101a261019d366004610bbc565b610839565b6040519081526020016100b5565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610308576102206001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087610990565b604051630ea598cb60e41b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ea598cb0906024016020604051808303815f875af1158015610284573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a89190610be4565b93506102de6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633866109fd565b508290507f0000000000000000000000000000000000000000000000000000000000000000610434565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03160361042e576103766001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087610990565b604051636e553f6560e01b8152600481018590523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303815f875af11580156103e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104049190610be4565b7f000000000000000000000000000000000000000000000000000000000000000091509150610434565b50829050815b9250929050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610593576104ab6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087610990565b604051636f074d1f60e11b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063de0e9a3e906024016020604051808303815f875af115801561050f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105339190610be4565b93506105696001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633866109fd565b508290507f0000000000000000000000000000000000000000000000000000000000000000610434565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03160361042e57604051635d043b2960e11b815260048101859052336024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ba087652906064016020604051808303815f875af115801561063d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106619190610be4565b7f000000000000000000000000000000000000000000000000000000000000000091509150610434565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156106d05750825b90505f8267ffffffffffffffff1660011480156106ec5750303b155b9050811580156106fa575080155b156107185760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561074257845460ff60401b1916600160401b1785555b6107976001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000005f19610a33565b6107ec6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000005f19610a33565b831561083257845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036109015760405162b0e38960e81b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0e38900906024015b602060405180830381865afa1580156108d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108fa9190610be4565b905061098a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036109875760405163ef8b30f760e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef8b30f7906024016108bb565b50805b92915050565b6040516001600160a01b0384811660248301528381166044830152606482018390526109f79186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610abe565b50505050565b6040516001600160a01b03838116602483015260448201839052610a2e91859182169063a9059cbb906064016109c5565b505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610a848482610b2e565b6109f7576040516001600160a01b0384811660248301525f6044830152610ab891869182169063095ea7b3906064016109c5565b6109f784825b5f8060205f8451602086015f885af180610add576040513d5f823e3d81fd5b50505f513d91508115610af4578060011415610b01565b6001600160a01b0384163b155b156109f757604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b5f805f8060205f8651602088015f8a5af192503d91505f519050828015610b6d57508115610b5f5780600114610b6d565b5f866001600160a01b03163b115b9695505050505050565b80356001600160a01b0381168114610b8d575f80fd5b919050565b5f8060408385031215610ba3575f80fd5b82359150610bb360208401610b77565b90509250929050565b5f8060408385031215610bcd575f80fd5b610bd683610b77565b946020939093013593505050565b5f60208284031215610bf4575f80fd5b505191905056fea2646970667358221220a2792c0bd658259d4e0b7b02c2509a924af25b7e3ba36c03ff199a1fdcc713f764736f6c634300081800330000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000dcee70654261af21c44c093c300ed3bb97b78192000000000000000000000000856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84", + "nonce": "0xe4", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionType": "CREATE", + "contractName": "TransparentUpgradeableProxy", + "contractAddress": "0x99db7619c018d61dbc2822767b63240d311d6992", + "function": null, + "arguments": [ + "0x7C31a924B01a20642aF2460d7Fe24A2FEf89074d", + "0xbB73f8a5B0074b27c6df026c77fA08B0111D017A", + "0x8129fc1c" + ], + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0xef8f4", + "value": "0x0", + "input": "0x60a060405260405162000e5038038062000e508339810160408190526200002691620003bc565b828162000034828262000099565b50508160405162000045906200035a565b6001600160a01b039091168152602001604051809103905ff0801580156200006f573d5f803e3d5ffd5b506001600160a01b0316608052620000906200008a60805190565b620000fe565b505050620004b3565b620000a4826200016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000f057620000eb8282620001ee565b505050565b620000fa62000267565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200013f5f8051602062000e30833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a16200016c8162000289565b50565b806001600160a01b03163b5f03620001aa57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516200020c919062000496565b5f60405180830381855af49150503d805f811462000246576040519150601f19603f3d011682016040523d82523d5f602084013e6200024b565b606091505b5090925090506200025e858383620002ca565b95945050505050565b3415620002875760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002b457604051633173bdd160e11b81525f6004820152602401620001a1565b805f8051602062000e30833981519152620001cd565b606082620002e357620002dd8262000330565b62000329565b8151158015620002fb57506001600160a01b0384163b155b156200032657604051639996b31560e01b81526001600160a01b0385166004820152602401620001a1565b50805b9392505050565b805115620003415780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6104fc806200093483390190565b80516001600160a01b03811681146200037f575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015620003b45781810151838201526020016200039a565b50505f910152565b5f805f60608486031215620003cf575f80fd5b620003da8462000368565b9250620003ea6020850162000368565b60408501519092506001600160401b038082111562000407575f80fd5b818601915086601f8301126200041b575f80fd5b81518181111562000430576200043062000384565b604051601f8201601f19908116603f011681019083821181831017156200045b576200045b62000384565b8160405282815289602084870101111562000474575f80fd5b6200048783602083016020880162000398565b80955050505050509250925092565b5f8251620004a981846020870162000398565b9190910192915050565b608051610469620004cb5f395f601001526104695ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102069190610407565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff80821115610381575f80fd5b818501915085601f830112610394575f80fd5b8135818111156103a6576103a661032a565b604051601f8201601f19908116603f011681019083821181831017156103ce576103ce61032a565b816040528281528860208487010111156103e6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610426576020818601810151858301520161040c565b505f92019182525091905056fea264697066735822122055a96d9f6d94a6ea50b308b2fc4aa0566df833e7551386bf651c4f24b0cc8f0a64736f6c63430008180033608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61030000000000000000000000007c31a924b01a20642af2460d7fe24a2fef89074d000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000", + "nonce": "0xe5", + "chainId": "0x1" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0x151057a14a4c84403e77c1fbc4f22a8156f63a4b", + "initCode": "0x608060405234801561000f575f80fd5b506040516104fc3803806104fc83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610407806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea2646970667358221220adbbc4425922655b0b518570c1f1ea2803ed1402d9e8c09bdf19a05b4208da4664736f6c63430008180033000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionType": "CALL", + "contractName": "TransparentUpgradeableProxy", + "contractAddress": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "gas": "0x48b37", + "value": "0x0", + "input": "0x0415cc15000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d69750000000000000000000000008face3283e20b19d98a7a132274b69c1304d60b400000000000000000000000035ec69a77b79c255e5d47d5a3bdbefefe342630c000000000000000000000000323c933df2523d5b0c756210446eee0fb84270fd", + "nonce": "0xe6", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionType": "CALL", + "contractName": "TransparentUpgradeableProxy", + "contractAddress": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "gas": "0x67646", + "value": "0x0", + "input": "0x0cc2250f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000035ec69a77b79c255e5d47d5a3bdbefefe342630c00000000000000000000000073bc33999c34a5126ca19dc900f22690c288d55e000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975000000000000000000000000a08f39d30dc865cc11a49b6e5cbd27630d6141c300000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d697500000000000000000000000015519e68ca7544d1c919a2a6e9065375a1f0c80a0000000000000000000000000000000000000000000000000000000000000019796e4c534465205769746864726177616c204d616e61676572000000000000000000000000000000000000000000000000000000000000000000000000000008796e4c534465574d000000000000000000000000000000000000000000000000", + "nonce": "0xe7", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa4a1e959ec7c78baf4f7d509f72b0d04de335744dee26d1119caf5bb2bb0a205", + "transactionType": "CREATE", + "contractName": "ynEigen", + "contractAddress": "0x989c5e2509c501deb6195b9f525d9092514041b4", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x2eacdb", + "value": "0x0", + "input": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000d5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d25780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61291080620000e35f395ff3fe608060405234801561000f575f80fd5b5060043610610260575f3560e01c806363d8882a1161014b578063a9059cbb116100bf578063dd62ed3e11610084578063dd62ed3e1461059e578063e0c784a6146105b1578063e63ab1e9146105d1578063f11b8188146105f8578063f45346dc14610617578063fb1bb9de1461062a575f80fd5b8063a9059cbb1461052a578063b8f82b261461053d578063cbe52ae314610550578063cd88e55814610563578063d547741f1461058b575f80fd5b80638ffbf6db116101105780638ffbf6db146104ab57806391d14854146104be57806395d89b41146104d1578063979d7e86146104d9578063a1a25e6e146104ec578063a217fddf14610523575f80fd5b806363d8882a146104415780636c401b9e1461044957806370a082311461045c5780638936a91f146104905780638d25239314610498575f80fd5b8063313ce567116101e25780634cdad506116101a75780634cdad506146103b657806350603df3146103c957806352f94f98146103dc5780635f4caf461461040757806360da3e831461041a57806361fd0ae11461042e575f80fd5b8063313ce5671461035b57806336568abe1461036a57806338bca6c81461037d5780633e5541f11461039057806342966c68146103a3575f80fd5b806318160ddd1161022857806318160ddd146102d457806323b872dd146102fb578063248a9ca31461030e578063282c51f3146103215780632f2ff15d14610348575f80fd5b806301e1d1141461026457806301ffc9a71461027f57806302191980146102a257806306fdde03146102ac578063095ea7b3146102c1575b5f80fd5b61026c61063e565b6040519081526020015b60405180910390f35b61029261028d36600461219a565b6106ad565b6040519015158152602001610276565b6102aa6106e3565b005b6102b4610767565b60405161027691906121c1565b6102926102cf366004612231565b610827565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025461026c565b61029261030936600461225b565b61083e565b61026c61031c366004612299565b610863565b61026c7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b6102aa6103563660046122b0565b610883565b60405160128152602001610276565b6102aa6103783660046122b0565b6108a5565b6102aa61038b366004612326565b6108dd565b61026c61039e366004612231565b610bae565b6102aa6103b1366004612299565b610c68565b61026c6103c4366004612299565b610ca0565b61026c6103d7366004612231565b610cab565b6001546103ef906001600160a01b031681565b6040516001600160a01b039091168152602001610276565b61029261041536600461238d565b610d64565b60025461029290600160a01b900460ff1681565b6102aa61043c3660046123bc565b610dd0565b6102aa610df1565b6102aa6104573660046122b0565b610e55565b61026c61046a36600461238d565b6001600160a01b03165f9081525f8051602061287b833981519152602052604090205490565b6102aa610fba565b6102aa6104a636600461247c565b611035565b6102aa6104b93660046123bc565b611387565b6102926104cc3660046122b0565b6113a9565b6102b46113df565b6002546103ef906001600160a01b031681565b6102926104fa36600461238d565b6001600160a01b03165f9081525f8051602061285b833981519152602052604090205460ff1690565b61026c5f81565b610292610538366004612231565b61141d565b61026c61054b366004612231565b61142a565b61026c61055e366004612231565b611435565b61026c61057136600461238d565b6001600160a01b03165f9081526020819052604090205490565b6102aa6105993660046122b0565b611440565b61026c6105ac3660046124b4565b61145c565b6105c46105bf3660046124e0565b6114a5565b604051610276919061251f565b61026c7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b61026c61060636600461238d565b5f6020819052908152604090205481565b61026c610625366004612562565b61156f565b61026c5f8051602061289b83398151915281565b600254604080516278744560e21b815290515f926001600160a01b0316916301e1d1149160048083019260209291908290030181865afa158015610684573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106a891906125a1565b905090565b5f6001600160e01b03198216637965db0b60e01b14806106dd57506301ffc9a760e01b6001600160e01b03198316145b92915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61070d816115da565b6002805460ff60a01b1916600160a01b908117918290556040517f9723f28d4abaff5df0f62bfb2418f2aac4a739b259edf209b8dc9944fa85aa789261075c92900460ff161515815260200190565b60405180910390a150565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060915f8051602061287b833981519152916107a5906125b8565b80601f01602080910402602001604051908101604052809291908181526020018280546107d1906125b8565b801561081c5780601f106107f35761010080835404028352916020019161081c565b820191905f5260205f20905b8154815290600101906020018083116107ff57829003601f168201915b505050505091505090565b5f336108348185856115e7565b5060019392505050565b5f3361084b8582856115f4565b610856858585611651565b60019150505b9392505050565b5f9081525f805160206128bb833981519152602052604090206001015490565b61088c82610863565b610895816115da565b61089f83836116ae565b50505050565b6001600160a01b03811633146108ce5760405163334bd91960e11b815260040160405180910390fd5b6108d8828261174f565b505050565b6001546001600160a01b0316331461090f576040516347ed65b360e11b81523360048201526024015b60405180910390fd5b8281811461093a57604051637df4c78160e01b81526004810182905260248101839052604401610906565b6001546001600160a01b03165f5b82811015610ba5575f878783818110610963576109636125f0565b9050602002016020810190610978919061238d565b600254604051632fa657a360e11b81526001600160a01b038084166004830152929350911690635f4caf4690602401602060405180830381865afa1580156109c2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e69190612604565b610a0e5760405163ee84f40b60e01b81526001600160a01b0382166004820152602401610906565b6001600160a01b0381165f908152602081815260409182902082519182019092529054808252878785818110610a4657610a466125f0565b905060200201351115610aa35780518290888886818110610a6957610a696125f0565b60405163a8c6953f60e01b81526001600160a01b039095166004860152602485019390935250602090910201356044820152606401610906565b868684818110610ab557610ab56125f0565b905060200201355f80846001600160a01b03166001600160a01b031681526020019081526020015f205f015f828254610aee9190612637565b90915550610b2a905084888886818110610b0a57610b0a6125f0565b90506020020135846001600160a01b03166117c89092919063ffffffff16565b7f4104800de83c5a3ae29f33899a811406b39aa89930fcc75e60d84b411803368d82888886818110610b5e57610b5e6125f0565b9050602002013586604051610b93939291906001600160a01b0393841681526020810192909252909116604082015260600190565b60405180910390a15050600101610948565b50505050505050565b5f610bb883610d64565b15610c4457600254604051631cbf960d60e01b81526001600160a01b038581166004830152602482018590525f921690631cbf960d90604401602060405180830381865afa158015610c0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c3091906125a1565b9050610c3c815f611827565b9150506106dd565b60405163ee84f40b60e01b81526001600160a01b0384166004820152602401610906565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610c92816115da565b610c9c3383611884565b5050565b5f6106dd825f6118b8565b5f610cb583610d64565b610cdd5760405163ee84f40b60e01b81526001600160a01b0384166004820152602401610906565b6002546001600160a01b031663833eaaf584610cf9855f6118b8565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015610d40573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085c91906125a1565b600254604051632fa657a360e11b81526001600160a01b0383811660048301525f921690635f4caf4690602401602060405180830381865afa158015610dac573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106dd9190612604565b5f8051602061289b833981519152610de7816115da565b610c9c825f61190f565b5f8051602061289b833981519152610e08816115da565b6002805460ff60a01b1916908190556040517f9723f28d4abaff5df0f62bfb2418f2aac4a739b259edf209b8dc9944fa85aa789161075c91600160a01b90910460ff161515815260200190565b815f03610e7557604051631f2a200560e01b815260040160405180910390fd5b6001546001600160a01b0316338114801590610f025750806001600160a01b0316637d1f8a816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ec8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eec919061264a565b6001600160a01b0316336001600160a01b031614155b15610f205760405163c183bcef60e01b815260040160405180910390fd5b6001600160a01b0382165f90815260208190526040812054610f43908590612665565b6001600160a01b0384165f818152602081905260409020829055909150610f6c903330876119aa565b60408051858152602081018390526001600160a01b0385168183015290517f2ebfd830bd582d0fa7c1920a304f9f8d532773cdf55b9deed77384b52cac29269181900360600190a150505050565b5f8051602061289b833981519152610fd1816115da565b7f7e7ba5b20f89141f0255e9704ce6ce6e55f5f28e4fc0d626fc76bedba3053201805460ff191690556040515f8051602061285b833981519152907f5b1b646968864ea75fad546d8c819e0de710df0bf61f658f6ba54dc587472e7b905f90a15050565b611045606082016040830161238d565b6001600160a01b03811661106c5760405163d92e233d60e01b815260040160405180910390fd5b61107c60a083016080840161238d565b6001600160a01b0381166110a35760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156110e85750825b90505f8267ffffffffffffffff1660011480156111045750303b155b905081158015611112575080155b156111305760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561115a57845460ff60401b1916600160401b1785555b6111626119e3565b61116a6119ed565b6111f16111778980612678565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506111b89250505060208b018b612678565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506119fd92505050565b61120a5f61120560a08b0160808c0161238d565b6116ae565b5061123f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61120560c08b0160a08c0161238d565b506112615f8051602061289b83398151915261120560e08b0160c08c0161238d565b506112726060890160408a0161238d565b600280546001600160a01b0319166001600160a01b03929092169190911790556112a26080890160608a0161238d565b600180546001600160a01b0319166001600160a01b03929092169190911781557f7e7ba5b20f89141f0255e9704ce6ce6e55f5f28e4fc0d626fc76bedba3053201805460ff191690911790556113376112fe60e08a018a6126bb565b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506001925061190f915050565b831561137d57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f8051602061289b83398151915261139e816115da565b610c9c82600161190f565b5f9182525f805160206128bb833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f8051602061287b833981519152916107a5906125b8565b5f33610834818585611651565b5f61085c8383610bae565b5f61085c8383610cab565b61144982610863565b611452816115da565b61089f838361174f565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b6060818067ffffffffffffffff8111156114c1576114c16123a8565b6040519080825280602002602001820160405280156114ea578160200160208202803683370190505b5091505f5b81811015611567575f8086868481811061150b5761150b6125f0565b9050602002016020810190611520919061238d565b6001600160a01b03166001600160a01b031681526020019081526020015f205f0154838281518110611554576115546125f0565b60209081029190910101526001016114ef565b505092915050565b5f611578611a0f565b600254600160a01b900460ff16156115a3576040516313d0ff5960e31b815260040160405180910390fd5b6115af84848433611a59565b905061085c60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6115e48133611c13565b50565b6108d88383836001611c4c565b5f6115ff848461145c565b90505f19811461089f578181101561164357604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610906565b61089f84848484035f611c4c565b6001600160a01b03831661167a57604051634b637e8f60e11b81525f6004820152602401610906565b6001600160a01b0382166116a35760405163ec442f0560e01b81525f6004820152602401610906565b6108d8838383611d30565b5f5f805160206128bb8339815191526116c784846113a9565b611746575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556116fc3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019150506106dd565b5f9150506106dd565b5f5f805160206128bb83398151915261176884846113a9565b15611746575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a460019150506106dd565b6040516001600160a01b038381166024830152604482018390526108d891859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611dd9565b5f806118517f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b90505f61185c61063e565b9050815f0361186f5784925050506106dd565b61187b85838387611e45565b95945050505050565b6001600160a01b0382166118ad57604051634b637e8f60e11b81525f6004820152602401610906565b610c9c825f83611d30565b5f806118e27f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b9050805f036118f457839150506106dd565b6119078461190061063e565b8386611e45565b949350505050565b5f8051602061285b8339815191525f5b835181101561089f575f84828151811061193b5761193b6125f0565b6020908102919091018101516001600160a01b0381165f818152868452604090819020805460ff19168915159081179091559051908152919350917fac6d52e87f8a8fc486e04600668caffa28c149f8286b136c0f327b4499b8c723910160405180910390a25060010161191f565b6040516001600160a01b03848116602483015283811660448301526064820183905261089f9186918216906323b872dd906084016117f5565b6119eb611e87565b565b6119f5611e87565b6119eb611ed0565b611a05611e87565b610c9c8282611ed8565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901611a5357604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f611a6385610d64565b611a8b5760405163ee84f40b60e01b81526001600160a01b0386166004820152602401610906565b835f03611aab57604051631f2a200560e01b815260040160405180910390fd5b611ac06001600160a01b0386168330876119aa565b600254604051631cbf960d60e01b81526001600160a01b038781166004830152602482018790525f921690631cbf960d90604401602060405180830381865afa158015611b0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b3391906125a1565b9050611b3f815f611827565b9150815f03611b6157604051639811e0c760e01b815260040160405180910390fd5b611b6b8483611eea565b6001600160a01b0386165f9081526020819052604081208054879290611b92908490612665565b909155505060408051868152602081018490526001600160a01b038089169287821692918716917feea1b3e3bf222477bec881b3d636cfbe1adfcf316ad14d2090fc98fdd2774c02910160405180910390a450949350505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b611c1d82826113a9565b610c9c5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610906565b5f8051602061287b8339815191526001600160a01b038516611c835760405163e602df0560e01b81525f6004820152602401610906565b6001600160a01b038416611cac57604051634a1406b160e11b81525f6004820152602401610906565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115611d2957836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051611d2091815260200190565b60405180910390a35b5050505050565b7f7e7ba5b20f89141f0255e9704ce6ce6e55f5f28e4fc0d626fc76bedba3053201545f8051602061285b8339815191529060ff168015611d8857506001600160a01b0384165f9081526020829052604090205460ff16155b8015611d9c57506001600160a01b03841615155b8015611db057506001600160a01b03831615155b15611dce57604051636ab17e0560e01b815260040160405180910390fd5b61089f848484611f1e565b5f8060205f8451602086015f885af180611df8576040513d5f823e3d81fd5b50505f513d91508115611e0f578060011415611e1c565b6001600160a01b0384163b155b1561089f57604051635274afe760e01b81526001600160a01b0385166004820152602401610906565b5f611e72611e5283612057565b8015611e6d57505f8480611e6857611e68612701565b868809115b151590565b611e7d868686612083565b61187b9190612665565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166119eb57604051631afcd79f60e31b815260040160405180910390fd5b611bed611e87565b611ee0611e87565b610c9c8282612139565b6001600160a01b038216611f135760405163ec442f0560e01b81525f6004820152602401610906565b610c9c5f8383611d30565b5f8051602061287b8339815191526001600160a01b038416611f585781816002015f828254611f4d9190612665565b90915550611fc89050565b6001600160a01b0384165f9081526020829052604090205482811015611faa5760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610906565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b038316611fe6576002810180548390039055612004565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161204991815260200190565b60405180910390a350505050565b5f600282600381111561206c5761206c612715565b6120769190612729565b60ff166001149050919050565b5f838302815f1985870982811083820303915050805f036120b7578382816120ad576120ad612701565b049250505061085c565b8084116120ce576120ce6003851502601118612189565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b612141611e87565b5f8051602061287b8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0361217a848261279a565b506004810161089f838261279a565b634e487b715f52806020526024601cfd5b5f602082840312156121aa575f80fd5b81356001600160e01b03198116811461085c575f80fd5b5f602080835283518060208501525f5b818110156121ed578581018301518582016040015282016121d1565b505f604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b03811681146115e4575f80fd5b803561222c8161220d565b919050565b5f8060408385031215612242575f80fd5b823561224d8161220d565b946020939093013593505050565b5f805f6060848603121561226d575f80fd5b83356122788161220d565b925060208401356122888161220d565b929592945050506040919091013590565b5f602082840312156122a9575f80fd5b5035919050565b5f80604083850312156122c1575f80fd5b8235915060208301356122d38161220d565b809150509250929050565b5f8083601f8401126122ee575f80fd5b50813567ffffffffffffffff811115612305575f80fd5b6020830191508360208260051b850101111561231f575f80fd5b9250929050565b5f805f8060408587031215612339575f80fd5b843567ffffffffffffffff80821115612350575f80fd5b61235c888389016122de565b90965094506020870135915080821115612374575f80fd5b50612381878288016122de565b95989497509550505050565b5f6020828403121561239d575f80fd5b813561085c8161220d565b634e487b7160e01b5f52604160045260245ffd5b5f60208083850312156123cd575f80fd5b823567ffffffffffffffff808211156123e4575f80fd5b818501915085601f8301126123f7575f80fd5b813581811115612409576124096123a8565b8060051b604051601f19603f8301168101818110858211171561242e5761242e6123a8565b60405291825284820192508381018501918883111561244b575f80fd5b938501935b828510156124705761246185612221565b84529385019392850192612450565b98975050505050505050565b5f6020828403121561248c575f80fd5b813567ffffffffffffffff8111156124a2575f80fd5b8201610100818503121561085c575f80fd5b5f80604083850312156124c5575f80fd5b82356124d08161220d565b915060208301356122d38161220d565b5f80602083850312156124f1575f80fd5b823567ffffffffffffffff811115612507575f80fd5b612513858286016122de565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b818110156125565783518352928401929184019160010161253a565b50909695505050505050565b5f805f60608486031215612574575f80fd5b833561257f8161220d565b92506020840135915060408401356125968161220d565b809150509250925092565b5f602082840312156125b1575f80fd5b5051919050565b600181811c908216806125cc57607f821691505b6020821081036125ea57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612614575f80fd5b8151801515811461085c575f80fd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156106dd576106dd612623565b5f6020828403121561265a575f80fd5b815161085c8161220d565b808201808211156106dd576106dd612623565b5f808335601e1984360301811261268d575f80fd5b83018035915067ffffffffffffffff8211156126a7575f80fd5b60200191503681900382131561231f575f80fd5b5f808335601e198436030181126126d0575f80fd5b83018035915067ffffffffffffffff8211156126ea575f80fd5b6020019150600581901b360382131561231f575f80fd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60ff83168061274757634e487b7160e01b5f52601260045260245ffd5b8060ff84160691505092915050565b601f8211156108d857805f5260205f20601f840160051c8101602085101561277b5750805b601f840160051c820191505b81811015611d29575f8155600101612787565b815167ffffffffffffffff8111156127b4576127b46123a8565b6127c8816127c284546125b8565b84612756565b602080601f8311600181146127fb575f84156127e45750858301515b5f19600386901b1c1916600185901b178555612852565b5f85815260208120601f198616915b828110156128295788860151825594840194600190910190840161280a565b508582101561284657878501515f19600388901b60f8161c191681555b505060018460011b0185555b50505050505056fe7e7ba5b20f89141f0255e9704ce6ce6e55f5f28e4fc0d626fc76bedba305320052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a2646970667358221220c4db2d6ad9745e7c68a074115b487b689351077c38afce86132b0b21de9c651564736f6c63430008180033", + "nonce": "0xe8", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe0562c7e3b23e3d02e4da2c337b2499b3aa4fb47b01166c18250738e0cbfd97e", + "transactionType": "CREATE", + "contractName": "AssetRegistry", + "contractAddress": "0x94db8f0d5bbccebf6d8288d06eb53bb80ca125bd", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x242d6f", + "value": "0x0", + "input": "0x608060405234801561000f575f80fd5b5061001861001d565b6100cf565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006d5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cc5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b611f81806100dc5f395ff3fe608060405234801561000f575f80fd5b50600436106101c6575f3560e01c806370807528116100fe578063c5f827e61161009e578063e63ab1e91161006e578063e63ab1e9146103ed578063efe0b29c14610414578063fb1bb9de14610427578063fc1198c01461044e575f80fd5b8063c5f827e614610390578063c92110c314610398578063cf35bdd0146103c7578063d547741f146103da575f80fd5b8063949db658116100d9578063949db6581461034a5780639a2be4af14610362578063a217fddf14610375578063a4b32de81461037c575f80fd5b80637080752814610311578063833eaaf51461032457806391d1485414610337575f80fd5b806336568abe116101695780635f4caf46116101445780635f4caf46146102c7578063613e85ff146102da57806367e4ac2c146102ef5780636be1fcc314610304575f80fd5b806336568abe1461026957806339b70e381461027c57806341fee44a146102a7575f80fd5b80631cbf960d116101a45780631cbf960d1461021d578063248a9ca314610230578063298410e5146102435780632f2ff15d14610256575f80fd5b806301e1d114146101ca57806301ffc9a7146101e557806315e09f3c14610208575b5f80fd5b6101d2610456565b6040519081526020015b60405180910390f35b6101f86101f33660046119dc565b6104e0565b60405190151581526020016101dc565b61021b610216366004611a1e565b610516565b005b6101d261022b366004611a39565b610802565b6101d261023e366004611a63565b610932565b61021b610251366004611a1e565b610952565b61021b610264366004611a7a565b6109c3565b61021b610277366004611a7a565b6109e5565b60035461028f906001600160a01b031681565b6040516001600160a01b0390911681526020016101dc565b6102ba6102b5366004611a1e565b610a18565b6040516101dc9190611adc565b6101f86102d5366004611a1e565b610a78565b6102e2610aae565b6040516101dc9190611aee565b6102f7610de1565b6040516101dc9190611b31565b6002546101f89060ff1681565b61021b61031f366004611a1e565b610e40565b6101d2610332366004611a39565b610f47565b6101f8610345366004611a7a565b611056565b60025461028f9061010090046001600160a01b031681565b60045461028f906001600160a01b031681565b6101d25f81565b6101d25f80516020611f0c83398151915281565b61021b61108c565b6103ba6103a6366004611a1e565b60016020525f908152604090205460ff1681565b6040516101dc9190611b71565b61028f6103d5366004611a63565b6110fd565b61021b6103e8366004611a7a565b611124565b6101d27f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b61021b610422366004611b7f565b611140565b6101d27f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a81565b61021b6114cd565b5f8080610461610aae565b5f80549192505b818110156104d7575f6104c05f838154811061048657610486611bb7565b905f5260205f20015f9054906101000a90046001600160a01b03168584815181106104b3576104b3611bb7565b6020026020010151610802565b90506104cc8186611bdf565b945050600101610468565b50919392505050565b5f6001600160e01b03198216637965db0b60e01b148061051057506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f80516020611f0c83398151915261052d81611531565b816001600160a01b0381166105555760405163d92e233d60e01b815260040160405180910390fd5b60025460ff1615610579576040516313d0ff5960e31b815260040160405180910390fd5b60026001600160a01b0384165f9081526001602052604090205460ff1660028111156105a7576105a7611aa8565b146105d557604051631005a45f60e21b81526001600160a01b03841660048201526024015b60405180910390fd5b600480546040516319b11cab60e31b81526001600160a01b03868116938201939093525f929091169063cd88e55890602401602060405180830381865afa158015610622573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106469190611bf2565b9050801561066a57604051631f17ea1d60e01b8152600481018290526024016105cc565b6003546040516374f2ca0560e01b81526001600160a01b0386811660048301525f9216906374f2ca0590602401602060405180830381865afa1580156106b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d69190611bf2565b905080156106fa57604051636f024b5160e01b8152600481018290526024016105cc565b5f6107048661153e565b5f80549192509061071790600190611c09565b8154811061072757610727611bb7565b5f91825260208220015481546001600160a01b0390911691908390811061075057610750611bb7565b5f918252602082200180546001600160a01b0319166001600160a01b03939093169290921790915580548061078757610787611c1c565b5f82815260208082205f19908401810180546001600160a01b03191690559092019092556001600160a01b03881680835260018252604092839020805460ff1916905591518381527ff166ed9d03804d1c092d69ed29c647b801c58174de928eff484aa9c92f4d5134910160405180910390a2505050505050565b6002546040516305d4ec6560e11b81526001600160a01b0384811660048301525f92839261010090910490911690630ba9d8ca90602401602060405180830381865afa158015610854573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108789190611bf2565b90505f846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108db9190611c30565b90508060ff1660120361090a57670de0b6b3a76400006108fb8584611c50565b6109059190611c67565b610929565b61091581600a611d66565b61091f8584611c50565b6109299190611c67565b95945050505050565b5f9081525f80516020611f2c833981519152602052604090206001015490565b5f80516020611f0c83398151915261096981611531565b816001600160a01b0381166109915760405163d92e233d60e01b815260040160405180910390fd5b60025460ff16156109b5576040516313d0ff5960e31b815260040160405180910390fd5b6109be836115b4565b505050565b6109cc82610932565b6109d581611531565b6109df83836117f4565b50505050565b6001600160a01b0381163314610a0e5760405163334bd91960e11b815260040160405180910390fd5b6109be8282611895565b60408051602080820183525f8083526001600160a01b0385168152600182528390208351918201909352825491929091829060ff166002811115610a5e57610a5e611aa8565b6002811115610a6f57610a6f611aa8565b90525092915050565b5f60016001600160a01b0383165f9081526001602052604090205460ff166002811115610aa757610aa7611aa8565b1492915050565b5f546060908067ffffffffffffffff811115610acc57610acc611d74565b604051908082528060200260200182016040528015610af5578160200160208202803683370190505b5060048054604051637063c25360e11b81529294506001600160a01b03169163e0c784a691610b26915f9101611d88565b5f60405180830381865afa158015610b40573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b679190810190611dcb565b6003546040516305b9289b60e11b81529193505f916001600160a01b0390911690630b72513690610b9c908490600401611d88565b5f60405180830381865afa158015610bb6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bdd9190810190611dcb565b905081815114610c0d5780516040516355c5b3e360e11b81526105cc918491600401918252602082015260400190565b60035460408051637d1f8a8160e01b815290515f926001600160a01b031691637d1f8a819160048083019260209291908290030181865afa158015610c54573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c789190611e84565b90505f8367ffffffffffffffff811115610c9457610c94611d74565b604051908082528060200260200182016040528015610cbd578160200160208202803683370190505b5090506001600160a01b03821615610d3f57604051637063c25360e11b81526001600160a01b0383169063e0c784a690610cfb905f90600401611d88565b5f60405180830381865afa158015610d15573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d3c9190810190611dcb565b90505b5f5b84811015610dd957838181518110610d5b57610d5b611bb7565b6020026020010151868281518110610d7557610d75611bb7565b60200260200101818151610d899190611bdf565b9052508151829082908110610da057610da0611bb7565b6020026020010151868281518110610dba57610dba611bb7565b60200260200101818151610dce9190611bdf565b905250600101610d41565b505050505090565b60605f805480602002602001604051908101604052809291908181526020018280548015610e3657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610e18575b5050505050905090565b5f80516020611f0c833981519152610e5781611531565b816001600160a01b038116610e7f5760405163d92e233d60e01b815260040160405180910390fd5b60025460ff1615610ea3576040516313d0ff5960e31b815260040160405180910390fd5b60016001600160a01b0384165f9081526001602052604090205460ff166002811115610ed157610ed1611aa8565b14610efa57604051637f93962560e01b81526001600160a01b03841660048201526024016105cc565b6001600160a01b0383165f81815260016020526040808220805460ff19166002179055517ffc9274ad64ab0a7d8dedd8c9297fb4e25d7a17eb057457c6bcf2a8f13dc8859c9190a2505050565b6002546040516305d4ec6560e11b81526001600160a01b0384811660048301525f92839261010090910490911690630ba9d8ca90602401602060405180830381865afa158015610f99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbd9190611bf2565b90505f846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ffc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110209190611c30565b90508060ff1660120361104057816108fb85670de0b6b3a7640000611c50565b8161104c82600a611d66565b61091f9086611c50565b5f9182525f80516020611f2c833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6110b681611531565b6002805460ff191660019081179091556040519081527f31311016d7204faff81880133e3db244ae8a8b9ce15e83e2432258226d15f942906020015b60405180910390a150565b5f818154811061110b575f80fd5b5f918252602090912001546001600160a01b0316905081565b61112d82610932565b61113681611531565b6109df8383611895565b6111506040820160208301611a1e565b6001600160a01b0381166111775760405163d92e233d60e01b815260040160405180910390fd5b61118760a0830160808401611a1e565b6001600160a01b0381166111ae5760405163d92e233d60e01b815260040160405180910390fd5b6111be60c0840160a08501611a1e565b6001600160a01b0381166111e55760405163d92e233d60e01b815260040160405180910390fd5b6111f560e0850160c08601611a1e565b6001600160a01b03811661121c5760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156112615750825b90505f8267ffffffffffffffff16600114801561127d5750303b155b90508115801561128b575080155b156112a95760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156112d357845460ff60401b1916600160401b1785555b6112db61190e565b6112e3611918565b6112fc5f6112f760a08d0160808e01611a1e565b6117f4565b506113317f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6112f760c08d0160a08e01611a1e565b506113667f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a6112f760e08d0160c08e01611a1e565b506113895f80516020611f0c8339815191526112f76101008d0160e08e01611a1e565b5061139a60608b0160408c01611a1e565b600380546001600160a01b0319166001600160a01b03929092169190911790556113ca60408b0160208c01611a1e565b600280546001600160a01b039290921661010002610100600160a81b031990921691909117905561140160808b0160608c01611a1e565b600480546001600160a01b0319166001600160a01b03929092169190911790555f61142c8b80611e9f565b905090505f5b81811015611479576114716114478d80611e9f565b8381811061145757611457611bb7565b905060200201602081019061146c9190611a1e565b6115b4565b600101611432565b505083156114c157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b7f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a6114f781611531565b6002805460ff191690556040515f81527f31311016d7204faff81880133e3db244ae8a8b9ce15e83e2432258226d15f942906020016110f2565b61153b8133611928565b50565b5f8054815b8181101561158f57836001600160a01b03165f828154811061156757611567611bb7565b5f918252602090912001546001600160a01b031603611587579392505050565b600101611543565b5060405163067c787f60e41b81526001600160a01b03841660048201526024016105cc565b6001600160a01b0381165f9081526001602052604081205460ff1660028111156115e0576115e0611aa8565b146116095760405163049437a360e21b81526001600160a01b03821660048201526024016105cc565b60035460405163551c457b60e11b81526001600160a01b0383811660048301529091169063aa388af690602401602060405180830381865afa158015611651573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116759190611eec565b61169d5760405163508516b160e11b81526001600160a01b03821660048201526024016105cc565b6002546040516305d4ec6560e11b81526001600160a01b03838116600483015261010090920490911690630ba9d8ca90602401602060405180830381865afa925050508015611709575060408051601f3d908101601f1916820190925261170691810190611bf2565b60015b61173157604051633a798e4760e21b81526001600160a01b03821660048201526024016105cc565b505f8054600180820183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390910180546001600160a01b0319166001600160a01b0385169081179091556040805160208082018352848252928552918390529092208251815491929091839160ff19909116908360028111156117b7576117b7611aa8565b0217905550506040516001600160a01b03831691507f0e3c58ebfb2e7465fbb1c32e6b4f40c3c4f5ca77e8218a386aff8617831260d7905f90a250565b5f5f80516020611f2c83398151915261180d8484611056565b61188c575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556118423390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610510565b5f915050610510565b5f5f80516020611f2c8339815191526118ae8484611056565b1561188c575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610510565b611916611965565b565b611920611965565b6119166119ae565b6119328282611056565b6119615760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016105cc565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661191657604051631afcd79f60e31b815260040160405180910390fd5b6119b6611965565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f602082840312156119ec575f80fd5b81356001600160e01b031981168114611a03575f80fd5b9392505050565b6001600160a01b038116811461153b575f80fd5b5f60208284031215611a2e575f80fd5b8135611a0381611a0a565b5f8060408385031215611a4a575f80fd5b8235611a5581611a0a565b946020939093013593505050565b5f60208284031215611a73575f80fd5b5035919050565b5f8060408385031215611a8b575f80fd5b823591506020830135611a9d81611a0a565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b60038110611ad857634e487b7160e01b5f52602160045260245ffd5b9052565b5f602082019050610510828451611abc565b602080825282518282018190525f9190848201906040850190845b81811015611b2557835183529284019291840191600101611b09565b50909695505050505050565b602080825282518282018190525f9190848201906040850190845b81811015611b255783516001600160a01b031683529284019291840191600101611b4c565b602081016105108284611abc565b5f60208284031215611b8f575f80fd5b813567ffffffffffffffff811115611ba5575f80fd5b82016101008185031215611a03575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561051057610510611bcb565b5f60208284031215611c02575f80fd5b5051919050565b8181038181111561051057610510611bcb565b634e487b7160e01b5f52603160045260245ffd5b5f60208284031215611c40575f80fd5b815160ff81168114611a03575f80fd5b808202811582820484141761051057610510611bcb565b5f82611c8157634e487b7160e01b5f52601260045260245ffd5b500490565b600181815b80851115611cc057815f1904821115611ca657611ca6611bcb565b80851615611cb357918102915b93841c9390800290611c8b565b509250929050565b5f82611cd657506001610510565b81611ce257505f610510565b8160018114611cf85760028114611d0257611d1e565b6001915050610510565b60ff841115611d1357611d13611bcb565b50506001821b610510565b5060208310610133831016604e8410600b8410161715611d41575081810a610510565b611d4b8383611c86565b805f1904821115611d5e57611d5e611bcb565b029392505050565b5f611a0360ff841683611cc8565b634e487b7160e01b5f52604160045260245ffd5b602080825282548282018190525f8481528281209092916040850190845b81811015611b255783546001600160a01b031683526001938401939285019201611da6565b5f6020808385031215611ddc575f80fd5b825167ffffffffffffffff80821115611df3575f80fd5b818501915085601f830112611e06575f80fd5b815181811115611e1857611e18611d74565b8060051b604051601f19603f83011681018181108582111715611e3d57611e3d611d74565b604052918252848201925083810185019188831115611e5a575f80fd5b938501935b82851015611e7857845184529385019392850192611e5f565b98975050505050505050565b5f60208284031215611e94575f80fd5b8151611a0381611a0a565b5f808335601e19843603018112611eb4575f80fd5b83018035915067ffffffffffffffff821115611ece575f80fd5b6020019150600581901b3603821315611ee5575f80fd5b9250929050565b5f60208284031215611efc575f80fd5b81518015158114611a03575f80fdfeb1fadd3142ab2ad7f1337ea4d97112bcc8337fc11ce5b20cb04ad038adf9981902dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a26469706673582212202bc73c64ff62a7920eb60caaec459a4b1643d8fcf808425414b733de6b8cb45164736f6c63430008180033", + "nonce": "0xe9", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8df6e23b8b16c375e9a66a4e39b1d69ee3ed0cfe84afbc9bf32956fa5f4b1eb4", + "transactionType": "CREATE", + "contractName": "TokenStakingNodesManager", + "contractAddress": "0x81f34d0db58a7934549d9b2b1e76542ed9801b1f", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x23bc82", + "value": "0x0", + "input": "0x608060405234801561000f575f80fd5b5061001861001d565b6100cf565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006d5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cc5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b611f2e806100dc5f395ff3fe608060405234801562000010575f80fd5b5060043610620001f8575f3560e01c8063a217fddf1162000113578063d547741f11620000ab578063ea4d3c9b1162000077578063ea4d3c9b14620004b1578063f33de6c014620004c5578063f9645e7414620004ce578063fb1bb9de14620004e5575f80fd5b8063d547741f1462000425578063e6319b41146200043c578063e63ab1e91462000461578063e967f4b61462000489575f80fd5b8063cb70bd7911620000eb578063cb70bd7914620003e6578063ce8572d314620003f0578063d131585d1462000407578063d26095201462000411575f80fd5b8063a217fddf146200039f578063a39cebe914620003a7578063c4240d2514620003be575f80fd5b80632f2ff15d116200019357806361464d2d116200015f57806361464d2d14620003305780637eb694a8146200034757806391d14854146200036f578063a1174e7d1462000386575f80fd5b80632f2ff15d14620002db57806336568abe14620002f257806339b70e38146200030957806352f94f98146200031c575f80fd5b80630e6a849611620001d35780630e6a849614620002645780631c53c2801462000294578063248a9ca314620002ab5780632d321fc714620002c2575f80fd5b806301ffc9a714620001fc57806304f67aa1146200022857806306a78ba6146200024d575b5f80fd5b620002136200020d366004620013b1565b6200050d565b60405190151581526020015b60405180910390f35b6200023e5f8051602062001eb983398151915281565b6040519081526020016200021f565b620002136200025e366004620013f6565b62000544565b6200027b6200027536600462001414565b62000571565b6040516001600160a01b0390911681526020016200021f565b6200027b620002a536600462001414565b620005ce565b6200023e620002bc36600462001414565b620005f7565b620002d9620002d3366004620013f6565b62000618565b005b620002d9620002ec3660046200142c565b62000727565b620002d9620003033660046200142c565b6200074f565b5f546200027b906001600160a01b031681565b6002546200027b906001600160a01b031681565b620002d96200034136600462001414565b6200078a565b6200023e7f9cb3b45ba8017381348975633951e84d77cd512b58a6ebd2533f422ddd94389081565b62000213620003803660046200142c565b620007e0565b6200039062000817565b6040516200021f91906200145d565b6200023e5f81565b620002d9620003b8366004620013f6565b62000879565b6200023e7fc54b323804427575ac6f9f18bf0a027fc2cb84d5af10f03a09d54fd69842fde981565b6200023e60055481565b6200021362000401366004620013f6565b620009d9565b6200027b62000a06565b6003546200027b906001600160a01b031681565b620002d9620004363660046200142c565b62000b81565b620002136200044d366004620013f6565b6002546001600160a01b0391821691161490565b6200023e7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6200023e7fd47f55d1ccb2b675ff4066bc639e489a7cb307c80ad9e87fc3104cf217c2b3ee81565b6001546200027b906001600160a01b031681565b6004546200023e565b620002d9620004df366004620014ab565b62000ba3565b6200023e7f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a81565b5f6001600160e01b03198216637965db0b60e01b14806200053e57506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6200053e7f9cb3b45ba8017381348975633951e84d77cd512b58a6ebd2533f422ddd94389083620007e0565b6004545f9082106200059e57604051631ca9e25f60e01b8152600481018390526024015b60405180910390fd5b60048281548110620005b457620005b4620014c3565b5f918252602090912001546001600160a01b031692915050565b60048181548110620005de575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f9081525f8051602062001ed9833981519152602052604090206001015490565b5f8051602062001eb983398151915262000632816200102e565b816001600160a01b0381166200065b5760405163d92e233d60e01b815260040160405180910390fd5b6003546001600160a01b031615620006865760405163a81fbfef60e01b815260040160405180910390fd5b8230604051620006969062001395565b6001600160a01b03928316815291166020820152604001604051809103905ff080158015620006c7573d5f803e3d5ffd5b50600380546001600160a01b0319166001600160a01b039283169081179091556040805191825291851660208201527fd13f13f7d12bbc1ec3c2f99ed663d6b643f722a4654c11d4325b35ed88d9fb7591015b60405180910390a1505050565b6200073282620005f7565b6200073d816200102e565b6200074983836200103d565b50505050565b6001600160a01b0381163314620007795760405163334bd91960e11b815260040160405180910390fd5b620007858282620010e5565b505050565b5f8051602062001eb9833981519152620007a4816200102e565b60058290556040518281527f5179ce38a6079ec731d2e265edcf9e1635e8ac7fd689ad42c5e20a7571c054159060200160405180910390a15050565b5f9182525f8051602062001ed9833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060048054806020026020016040519081016040528092919081815260200182805480156200086f57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831162000850575b5050505050905090565b5f8051602062001eb983398151915262000893816200102e565b816001600160a01b038116620008bc5760405163d92e233d60e01b815260040160405180910390fd5b6003546001600160a01b0316620008e657604051636aef646b60e11b815260040160405180910390fd5b600354604051631b2ce7f360e11b81526001600160a01b03858116600483015290911690633659cfe6906024015f604051808303815f87803b1580156200092b575f80fd5b505af11580156200093e573d5f803e3d5ffd5b505060045491505f90505b81811015620009905762000987600482815481106200096c576200096c620014c3565b5f918252602090912001546001600160a01b03168362001163565b60010162000949565b50604080516001600160a01b0386168152602081018390527f02c79c1e3f8b682a9487f84feb1ab388b1ebf7a5e85307e941ec19122d2ed14e910160405180910390a150505050565b5f6200053e7fd47f55d1ccb2b675ff4066bc639e489a7cb307c80ad9e87fc3104cf217c2b3ee83620007e0565b6003545f906001600160a01b03168062000a335760405163d92e233d60e01b815260040160405180910390fd5b7fc54b323804427575ac6f9f18bf0a027fc2cb84d5af10f03a09d54fd69842fde962000a5f816200102e565b600454600554811062000a8c57600554604051634ec828df60e11b81526004016200059591815260200190565b6003546040515f916001600160a01b03169062000aa990620013a3565b6001600160a01b0390911681526040602082018190525f90820152606001604051809103905ff08015801562000ae1573d5f803e3d5ffd5b5090508062000af1818462001163565b600480546001810182555f919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0383169081179091556040805185815260208101929092527fbf09b194225fb976ecbedf24587fc7de2987992ad982f5321a563ce92221000b910160405180910390a194505050505090565b62000b8c82620005f7565b62000b97816200102e565b620007498383620010e5565b62000bb26020820182620013f6565b6001600160a01b03811662000bda5760405163d92e233d60e01b815260040160405180910390fd5b62000bec60a0830160808401620013f6565b6001600160a01b03811662000c145760405163d92e233d60e01b815260040160405180910390fd5b62000c27610100840160e08501620013f6565b6001600160a01b03811662000c4f5760405163d92e233d60e01b815260040160405180910390fd5b62000c6361012085016101008601620013f6565b6001600160a01b03811662000c8b5760405163d92e233d60e01b815260040160405180910390fd5b62000c9f61014086016101208701620013f6565b6001600160a01b03811662000cc75760405163d92e233d60e01b815260040160405180910390fd5b62000cdb61016087016101408801620013f6565b6001600160a01b03811662000d035760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f8115801562000d495750825b90505f8267ffffffffffffffff16600114801562000d665750303b155b90508115801562000d75575080155b1562000d945760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831562000dbf57845460ff60401b1916600160401b1785555b62000dc9620012fe565b62000deb5f801b8d608001602081019062000de59190620013f6565b6200103d565b5062000e145f8051602062001eb98339815191528d60e001602081019062000de59190620013f6565b5062000e507f9cb3b45ba8017381348975633951e84d77cd512b58a6ebd2533f422ddd9438908d61010001602081019062000de59190620013f6565b5062000e8c7fc54b323804427575ac6f9f18bf0a027fc2cb84d5af10f03a09d54fd69842fde98d61012001602081019062000de59190620013f6565b5062000ec87fd47f55d1ccb2b675ff4066bc639e489a7cb307c80ad9e87fc3104cf217c2b3ee8d61014001602081019062000de59190620013f6565b5062000f037f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8d60a001602081019062000de59190620013f6565b5062000f3e7f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a8d60c001602081019062000de59190620013f6565b5062000f4e60208d018d620013f6565b5f80546001600160a01b0319166001600160a01b039290921691909117905562000f7f60408d0160208e01620013f6565b600180546001600160a01b0319166001600160a01b039290921691909117905562000fb160608d0160408e01620013f6565b600280546001600160a01b0319166001600160a01b039290921691909117905560608c013560055583156200102057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b6200103a81336200130a565b50565b5f5f8051602062001ed9833981519152620010598484620007e0565b620010db575f848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055620010903390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019150506200053e565b5f9150506200053e565b5f5f8051602062001ed9833981519152620011018484620007e0565b15620010db575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a460019150506200053e565b5f826001600160a01b031663b3c650156040518163ffffffff1660e01b8152600401602060405180830381865afa158015620011a1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620011c79190620014d7565b90508067ffffffffffffffff165f0362000785576040805180820182523081526020810184815291516377b3492760e01b815290516001600160a01b03908116600483015291516024820152908416906377b34927906044015f604051808303815f87803b15801562001238575f80fd5b505af11580156200124b573d5f803e3d5ffd5b50505050826001600160a01b031663b3c650156040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200128c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620012b29190620014d7565b604080516001600160a01b038616815267ffffffffffffffff831660208201529192507fa070c83df7efc58b668afb64705222890e09b4090d56ee9981fc66ac1c552aa191016200071a565b620013086200134b565b565b620013168282620007e0565b620013475760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440162000595565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166200130857604051631afcd79f60e31b815260040160405180910390fd5b610421806200150183390190565b610597806200192283390190565b5f60208284031215620013c2575f80fd5b81356001600160e01b031981168114620013da575f80fd5b9392505050565b6001600160a01b03811681146200103a575f80fd5b5f6020828403121562001407575f80fd5b8135620013da81620013e1565b5f6020828403121562001425575f80fd5b5035919050565b5f80604083850312156200143e575f80fd5b8235915060208301356200145281620013e1565b809150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156200149f5783516001600160a01b03168352928401929184019160010162001478565b50909695505050505050565b5f6101608284031215620014bd575f80fd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215620014e8575f80fd5b815167ffffffffffffffff81168114620013da575f80fdfe608060405234801561000f575f80fd5b5060405161042138038061042183398101604081905261002e9161015f565b806001600160a01b03811661005d57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006681610077565b50610070826100c6565b5050610190565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f036100fb5760405163211eb15960e21b81526001600160a01b0382166004820152602401610054565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b80516001600160a01b038116811461015a575f80fd5b919050565b5f8060408385031215610170575f80fd5b61017983610144565b915061018760208401610144565b90509250929050565b6102848061019d5f395ff3fe608060405234801561000f575f80fd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f80fd5b61006c610067366004610221565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c6100d6565b5f546001600160a01b031661007b565b61006c6100bd366004610221565b6100e9565b6100ca610128565b6100d381610154565b50565b6100de610128565b6100e75f6101d2565b565b6100f1610128565b6001600160a01b03811661011f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100d3816101d2565b5f546001600160a01b031633146100e75760405163118cdaa760e01b8152336004820152602401610116565b806001600160a01b03163b5f036101895760405163211eb15960e21b81526001600160a01b0382166004820152602401610116565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f60208284031215610231575f80fd5b81356001600160a01b0381168114610247575f80fd5b939250505056fea26469706673582212205220934962511be7ea7a268c3ed5e444d6b1301ddf31d457c8b666be316f12a864736f6c6343000818003360a060405260405161059738038061059783398101604081905261002291610376565b61002c828261003e565b506001600160a01b0316608052610465565b610047826100fb565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e905f90a28051156100ef576100ea826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e49190610431565b82610209565b505050565b6100f761027c565b5050565b806001600160a01b03163b5f0361013557604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b815290515f92841691635c60da1b9160048083019260209291908290030181865afa1580156101ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d29190610431565b9050806001600160a01b03163b5f036100f757604051634c9c8ce360e01b81526001600160a01b038216600482015260240161012c565b60605f80846001600160a01b031684604051610225919061044a565b5f60405180830381855af49150503d805f811461025d576040519150601f19603f3d011682016040523d82523d5f602084013e610262565b606091505b50909250905061027385838361029d565b95945050505050565b341561029b5760405163b398979f60e01b815260040160405180910390fd5b565b6060826102b2576102ad826102fc565b6102f5565b81511580156102c957506001600160a01b0384163b155b156102f257604051639996b31560e01b81526001600160a01b038516600482015260240161012c565b50805b9392505050565b80511561030c5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b80516001600160a01b038116811461033b575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b8381101561036e578181015183820152602001610356565b50505f910152565b5f8060408385031215610387575f80fd5b61039083610325565b60208401519092506001600160401b03808211156103ac575f80fd5b818501915085601f8301126103bf575f80fd5b8151818111156103d1576103d1610340565b604051601f8201601f19908116603f011681019083821181831017156103f9576103f9610340565b81604052828152886020848701011115610411575f80fd5b610422836020830160208801610354565b80955050505050509250929050565b5f60208284031215610441575f80fd5b6102f582610325565b5f825161045b818460208701610354565b9190910192915050565b60805161011b61047c5f395f601d015261011b5ff3fe6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f80375f80365f845af43d5f803e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f80fd5b81516001600160a01b038116811460de575f80fd5b939250505056fea26469706673582212202b8e47f9dbadb5e5b182ef67478f04e8f051fa0445601c532c82f3537586c39564736f6c6343000818003324791c44c040514a5d2580696fc45e7d3cb6c9fa65bf3db2e4755362d6c155b502dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a2646970667358221220a714eca5fda73806a0c22e20569ad7f1f1a1fe77566d27b8d71e68e561b04e7164736f6c63430008180033", + "nonce": "0xea", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xc231e03d016280344a8515fbc643c7a90bcb00510dd1568f0d539acb59c155e1", + "transactionType": "CREATE", + "contractName": "ynEigenDepositAdapter", + "contractAddress": "0x8ef7a066bf2cf76bad826c1de8d314badf057b52", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x18536b", + "value": "0x0", + "input": "0x608060405234801561000f575f80fd5b506115308061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610111575f3560e01c80639a2be4af1161009e578063b8f82b261161006e578063b8f82b261461023c578063c1fe3e481461024f578063d547741f14610262578063daba667d14610275578063f45346dc14610288575f80fd5b80639a2be4af146101fd578063a1d0362e1461020f578063a217fddf14610222578063ac210cc714610229575f80fd5b80632f2ff15d116100e45780632f2ff15d1461018657806336568abe146101995780634aa07e64146101ac5780634e6c9766146101d757806391d14854146101ea575f80fd5b806301ffc9a7146101155780630415cc151461013d578063248a9ca31461015257806329b6eca914610173575b5f80fd5b6101286101233660046112a2565b61029b565b60405190151581526020015b60405180910390f35b61015061014b3660046112dd565b6102d1565b005b61016561016036600461136c565b6105e7565b604051908152602001610134565b610150610181366004611383565b610607565b61015061019436600461139e565b610722565b6101506101a736600461139e565b610744565b6001546101bf906001600160a01b031681565b6040516001600160a01b039091168152602001610134565b6004546101bf906001600160a01b031681565b6101286101f836600461139e565b61077c565b5f546101bf906001600160a01b031681565b61016561021d3660046113cc565b6107b2565b6101655f81565b6005546101bf906001600160a01b031681565b61016561024a36600461141c565b6108a3565b6003546101bf906001600160a01b031681565b61015061027036600461139e565b610ada565b6002546101bf906001600160a01b031681565b610165610296366004611446565b610af6565b5f6001600160e01b03198216637965db0b60e01b14806102cb57506301ffc9a760e01b6001600160e01b03198316145b92915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156103165750825b90505f8267ffffffffffffffff1660011480156103325750303b155b905081158015610340575080155b1561035e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561038857845460ff60401b1916600160401b1785555b85516001600160a01b0381166103b15760405163d92e233d60e01b815260040160405180910390fd5b60208701516001600160a01b0381166103dd5760405163d92e233d60e01b815260040160405180910390fd5b60408801516001600160a01b0381166104095760405163d92e233d60e01b815260040160405180910390fd5b60608901516001600160a01b0381166104355760405163d92e233d60e01b815260040160405180910390fd5b61043d610bef565b61044d5f801b8b60600151610bf9565b5089515f80546001600160a01b039283166001600160a01b0319918216179091556020808d015160018054918516918416821790556040808f01516002805491909616941693909317909355815163183fc7c960e31b8152915163c1fe3e489260048082019392918290030181865afa1580156104cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104f09190611485565b600380546001600160a01b0319166001600160a01b03928316179055600254604080516338d52e0f60e01b8152905191909216916338d52e0f9160048083019260209291908290030181865afa15801561054c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105709190611485565b60045f6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050505083156105df57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f9081525f805160206114db833981519152602052604090206001015490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806106515750805467ffffffffffffffff808416911610155b1561066f5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b178155826001600160a01b0381166106b95760405163d92e233d60e01b815260040160405180910390fd5b50600580546001600160a01b0319166001600160a01b038516179055805460ff60401b1916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b61072b826105e7565b61073481610c9a565b61073e8383610bf9565b50505050565b6001600160a01b038116331461076d5760405163334bd91960e11b815260040160405180910390fd5b6107778282610ca7565b505050565b5f9182525f805160206114db833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f6001600160a01b0383166107da5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166108015760405163d92e233d60e01b815260040160405180910390fd5b826001600160a01b0316826001600160a01b03160361083357604051632af47b8760e11b815260040160405180910390fd5b61083e858585610af6565b60408051338152602081018790529081018290524260608201529091506001600160a01b0380841691878216918616907f5ec2325bfdc6696fa381751bb5a9994c005f28fabd0b7dc55488f18ce1a85ef19060800160405180910390a4949350505050565b6004545f906001600160a01b03908116908416036109a5576002546040516363737ac960e11b8152600481018490525f916001600160a01b03169063c6e6f59290602401602060405180830381865afa158015610902573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092691906114a0565b5f54600254604051635c7c159360e11b81526001600160a01b03918216600482015260248101849052929350169063b8f82b26906044015b602060405180830381865afa158015610979573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099d91906114a0565b9150506102cb565b6003546001600160a01b0390811690841603610a615760015460405162b0e38960e81b8152600481018490525f916001600160a01b03169063b0e3890090602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2591906114a0565b5f54600154604051635c7c159360e11b81526001600160a01b03918216600482015260248101849052929350169063b8f82b269060440161095e565b5f54604051635c7c159360e11b81526001600160a01b038581166004830152602482018590529091169063b8f82b2690604401602060405180830381865afa158015610aaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad391906114a0565b90506102cb565b610ae3826105e7565b610aec81610c9a565b61073e8383610ca7565b6003545f906001600160a01b0390811690851603610b1f57610b188383610d20565b9050610be8565b6004546001600160a01b0390811690851603610b3f57610b188383610ecd565b610b546001600160a01b03851633308661106c565b5f54610b6d906001600160a01b038681169116856110d3565b5f54604051633d14d1b760e21b81526001600160a01b0386811660048301526024820186905284811660448301529091169063f45346dc906064016020604051808303815f875af1158015610bc4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b1891906114a0565b9392505050565b610bf7611162565b565b5f5f805160206114db833981519152610c12848461077c565b610c91575f848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055610c473390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019150506102cb565b5f9150506102cb565b610ca481336111ab565b50565b5f5f805160206114db833981519152610cc0848461077c565b15610c91575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a460019150506102cb565b6003545f90610d3a906001600160a01b031633308661106c565b600554600354610d57916001600160a01b039182169116856110d3565b600554600354604051629dd64160e51b8152600481018690526001600160a01b0391821660248201525f9291909116906313bac8209060440160408051808303815f875af1158015610dab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dcf91906114b7565b505f54600154919250610def916001600160a01b039081169116836110d3565b5f54600154604051633d14d1b760e21b81526001600160a01b03918216600482015260248101849052858216604482015291169063f45346dc906064016020604051808303815f875af1158015610e48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6c91906114a0565b60035460408051878152602081018590529081018390529193506001600160a01b03908116919085169033907ff54c2631d8cb114d7a2dcd916b8d4bed6baae85cdf5444217c179e324cb2b907906060015b60405180910390a45092915050565b6004545f90610ee7906001600160a01b031633308661106c565b600554600454610f04916001600160a01b039182169116856110d3565b60055460048054604051629dd64160e51b81529182018690526001600160a01b0390811660248301525f9216906313bac8209060440160408051808303815f875af1158015610f55573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f7991906114b7565b505f54600254919250610f99916001600160a01b039081169116836110d3565b5f54600254604051633d14d1b760e21b81526001600160a01b03918216600482015260248101849052858216604482015291169063f45346dc906064016020604051808303815f875af1158015610ff2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101691906114a0565b60045460408051878152602081018590529081018390529193506001600160a01b03908116919085169033907ff54c2631d8cb114d7a2dcd916b8d4bed6baae85cdf5444217c179e324cb2b90790606001610ebe565b6040516001600160a01b03848116602483015283811660448301526064820183905261073e9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506111ed565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526111248482611259565b61073e576040516001600160a01b0384811660248301525f604483015261115891869182169063095ea7b3906064016110a1565b61073e84826111ed565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610bf757604051631afcd79f60e31b815260040160405180910390fd5b6111b5828261077c565b6111e95760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b5050565b5f8060205f8451602086015f885af18061120c576040513d5f823e3d81fd5b50505f513d91508115611223578060011415611230565b6001600160a01b0384163b155b1561073e57604051635274afe760e01b81526001600160a01b03851660048201526024016111e0565b5f805f8060205f8651602088015f8a5af192503d91505f5190508280156112985750811561128a5780600114611298565b5f866001600160a01b03163b115b9695505050505050565b5f602082840312156112b2575f80fd5b81356001600160e01b031981168114610be8575f80fd5b6001600160a01b0381168114610ca4575f80fd5b5f608082840312156112ed575f80fd5b6040516080810181811067ffffffffffffffff8211171561131c57634e487b7160e01b5f52604160045260245ffd5b604052823561132a816112c9565b8152602083013561133a816112c9565b6020820152604083013561134d816112c9565b60408201526060830135611360816112c9565b60608201529392505050565b5f6020828403121561137c575f80fd5b5035919050565b5f60208284031215611393575f80fd5b8135610be8816112c9565b5f80604083850312156113af575f80fd5b8235915060208301356113c1816112c9565b809150509250929050565b5f805f80608085870312156113df575f80fd5b84356113ea816112c9565b9350602085013592506040850135611401816112c9565b91506060850135611411816112c9565b939692955090935050565b5f806040838503121561142d575f80fd5b8235611438816112c9565b946020939093013593505050565b5f805f60608486031215611458575f80fd5b8335611463816112c9565b925060208401359150604084013561147a816112c9565b809150509250925092565b5f60208284031215611495575f80fd5b8151610be8816112c9565b5f602082840312156114b0575f80fd5b5051919050565b5f80604083850312156114c8575f80fd5b8251915060208301516113c1816112c956fe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a264697066735822122046485220ff419e922fa02920e5f0d14bd4f59caa7119cef98cf364272f24d72b64736f6c63430008180033", + "nonce": "0xeb", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xb22f97618e490063c02123570fd3bc8005735b9b5f63dc78c3e664462d6c9615", + "transactionType": "CREATE", + "contractName": "EigenStrategyManager", + "contractAddress": "0x1776dea5799fc7ad10b6039f6e1927fefd731e85", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x38a094", + "value": "0x0", + "input": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000d5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d25780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61321f80620000e35f395ff3fe608060405234801561000f575f80fd5b506004361061021e575f3560e01c80637c0867af1161012a578063ad7805e8116100b4578063da5be02211610079578063da5be0221461056b578063daba667d1461057e578063e63ab1e914610591578063ea4d3c9b146105b8578063fb1bb9de146105cb575f80fd5b8063ad7805e8146104f8578063af9ba2251461051f578063b9ceea0d14610532578063c1fe3e4814610545578063d547741f14610558575f80fd5b80639ab739d3116100fa5780639ab739d3146104765780639be323f41461049d578063a217fddf146104b1578063aa388af6146104b8578063ac210cc7146104e5575f80fd5b80637c0867af1461042b5780637d1f8a811461043e57806391d14854146104515780639a2be4af14610464575f80fd5b806336568abe116101ab5780634e6c97661161017b5780634e6c9766146103cc5780635ffcfdc7146103df57806372cb5d97146103f257806374f2ca051461040557806379e476b014610418575f80fd5b806336568abe1461035357806339b70e381461036657806339ebf823146103915780634aa07e64146103b9575f80fd5b80630b74ce8c116101f15780630b74ce8c146102d25780630dc3e02914610307578063248a9ca31461031a5780632c3bb44a1461032d5780632f2ff15d14610340575f80fd5b806301ffc9a71461022257806302b5cce31461024a5780630a82590c1461029d5780630b725136146102b2575b5f80fd5b6102356102303660046129b3565b6105f2565b60405190151581526020015b60405180910390f35b61027d6102583660046129f5565b600b6020525f90815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610241565b6102b06102ab3660046129f5565b610628565b005b6102c56102c0366004612a57565b610650565b6040516102419190612acf565b6102f97f5604e2fe54b4de17b81a5ded6f82357d742fd2722d67304e37ff20bd589b4f3881565b604051908152602001610241565b6102356103153660046129f5565b6107c5565b6102f9610328366004612ae1565b6107f0565b6102b061033b366004612af8565b610810565b6102b061034e366004612b40565b610ad8565b6102b0610361366004612b40565b610afa565b600154610379906001600160a01b031681565b6040516001600160a01b039091168152602001610241565b61037961039f3660046129f5565b60046020525f90815260409020546001600160a01b031681565b600554610379906001600160a01b031681565b600754610379906001600160a01b031681565b6102b06103ed366004612ca5565b610b32565b6102b0610400366004612d0c565b610b72565b6102f96104133660046129f5565b610d4f565b6102b0610426366004612d38565b610e53565b600354610379906001600160a01b031681565b600954610379906001600160a01b031681565b61023561045f366004612b40565b610eb7565b5f54610379906001600160a01b031681565b6102f97f1ce621c530dfade3239478366c4e5e2c9d62462d265362544aa805bfede55f8b81565b6102f95f805160206131ca83398151915281565b6102f95f81565b6102356104c63660046129f5565b6001600160a01b039081165f9081526004602052604090205416151590565b600a54610379906001600160a01b031681565b6102f97fe0d563514842a8c29151c49cd2698127f54dd344a9b2c74a42fe9be3e305fe9881565b6102f961052d366004612da6565b610eed565b6102b0610540366004612dd0565b610fb0565b600854610379906001600160a01b031681565b6102b0610566366004612b40565b611713565b6102b0610579366004612a57565b61172f565b600654610379906001600160a01b031681565b6102f97f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b600254610379906001600160a01b031681565b6102f97f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a81565b5f6001600160e01b03198216637965db0b60e01b148061062257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001600160a01b038082165f9081526004602052604090205461064d918391166117be565b50565b6060816001600160401b0381111561066a5761066a612b6e565b604051908082528060200260200182016040528015610693578160200160208202803683370190505b509050815f5b818110156107bd575f8585838181106106b4576106b4612e07565b90506020020160208101906106c991906129f5565b6001600160a01b038181165f818152600460208181526040808420548616808552600b8352938190208151808301835290546001600160801b03808216808452600160801b90920416938201849052600a549251636dbb88e360e11b81529485019690965260248401959095529596509194929391929091169063db7711c690604401602060405180830381865afa158015610767573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061078b9190612e1b565b6107959190612e32565b8685815181106107a7576107a7612e07565b6020908102919091010152505050600101610699565b505092915050565b5f6106227f1ce621c530dfade3239478366c4e5e2c9d62462d265362544aa805bfede55f8b83610eb7565b5f9081525f8051602061318a833981519152602052604090206001015490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff1680610859575080546001600160401b03808416911610155b156108775760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155846001600160a01b0381166108c05760405163d92e233d60e01b815260040160405180910390fd5b846001600160a01b0381166108e85760405163d92e233d60e01b815260040160405180910390fd5b6108f0611b4e565b600980546001600160a01b03808a166001600160a01b031992831617909255600a80549289169290911691909117905561094a7f1ce621c530dfade3239478366c4e5e2c9d62462d265362544aa805bfede55f8b86611b60565b506109757fe0d563514842a8c29151c49cd2698127f54dd344a9b2c74a42fe9be3e305fe9886611b60565b505f805f9054906101000a90046001600160a01b03166001600160a01b031663979d7e866040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109ea9190612e51565b6001600160a01b03166367e4ac2c6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a24573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a4b9190810190612e6c565b80519091505f5b81811015610a8557610a7d838281518110610a6f57610a6f612e07565b60200260200101515f6117be565b600101610a52565b5050835460ff60401b1916845550506040516001600160401b03841681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2915060200160405180910390a15050505050565b610ae1826107f0565b610aea81611c01565b610af48383611b60565b50505050565b6001600160a01b0381163314610b235760405163334bd91960e11b815260040160405180910390fd5b610b2d8282611c0b565b505050565b5f805160206131ca833981519152610b4981611c01565b610b51611c84565b610b5c848484611cbb565b610af460015f805160206131aa83398151915255565b7f5604e2fe54b4de17b81a5ded6f82357d742fd2722d67304e37ff20bd589b4f38610b9c81611c01565b826001600160a01b038116610bc45760405163d92e233d60e01b815260040160405180910390fd5b826001600160a01b038116610bec5760405163d92e233d60e01b815260040160405180910390fd5b846001600160a01b0316846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c569190612e51565b6001600160a01b031614610cf65784846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ca1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cc59190612e51565b60405163d779457160e01b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b6001600160a01b038581165f8181526004602052604080822080546001600160a01b0319169489169485179055517f5f6921933580ca0adbbb669ff049927ba73230114570507fc8e10f0758f1d8049190a35050505050565b6001600160a01b038181165f90815260046020526040812054909116610d935760405163508516b160e11b81526001600160a01b0383166004820152602401610ced565b6003546040805163a1174e7d60e01b815290515f926001600160a01b03169163a1174e7d91600480830192869291908290030181865afa158015610dd9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e009190810190612ef5565b80519091505f5b81811015610e4b575f838281518110610e2257610e22612e07565b60200260200101519050610e36868261224a565b610e409086612e32565b945050600101610e07565b505050919050565b7fe0d563514842a8c29151c49cd2698127f54dd344a9b2c74a42fe9be3e305fe98610e7d81611c01565b815f5b81811015610eb057610ea8858583818110610e9d57610e9d612e07565b905060800201612452565b600101610e80565b5050505050565b5f9182525f8051602061318a833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6001600160a01b038281165f90815260046020526040812054909116610f315760405163508516b160e11b81526001600160a01b0384166004820152602401610ced565b600354604051630735424b60e11b8152600481018490525f916001600160a01b031690630e6a849690602401602060405180830381865afa158015610f78573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f9c9190612e51565b9050610fa8848261224a565b949350505050565b610fc060808201606083016129f5565b6001600160a01b038116610fe75760405163d92e233d60e01b815260040160405180910390fd5b610ff760e0830160c084016129f5565b6001600160a01b03811661101e5760405163d92e233d60e01b815260040160405180910390fd5b61102f610100840160e085016129f5565b6001600160a01b0381166110565760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f8115801561109a5750825b90505f826001600160401b031660011480156110b55750303b155b9050811580156110c3575080155b156110e15760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561110b57845460ff60401b1916600160401b1785555b611113612743565b61112c5f61112760e08c0160c08d016129f5565b611b60565b506111637f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6111276101408c016101208d016129f5565b5061119a7f427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a6111276101208c016101008d016129f5565b506111bd5f805160206131ca8339815191526111276101008c0160e08d016129f5565b506111f47f5604e2fe54b4de17b81a5ded6f82357d742fd2722d67304e37ff20bd589b4f386111276101608c016101408d016129f5565b505f5b6112018a80612f7e565b905081101561149e575f6112158b80612f7e565b8381811061122557611225612e07565b905060200201602081019061123a91906129f5565b6001600160a01b0316148061128857505f61125860208c018c612f7e565b8381811061126857611268612e07565b905060200201602081019061127d91906129f5565b6001600160a01b0316145b156112a65760405163d92e233d60e01b815260040160405180910390fd5b5f6004816112b48d80612f7e565b858181106112c4576112c4612e07565b90506020020160208101906112d991906129f5565b6001600160a01b03908116825260208201929092526040015f2054161461134e576113048a80612f7e565b8281811061131457611314612e07565b905060200201602081019061132991906129f5565b604051634af8dd4d60e11b81526001600160a01b039091166004820152602401610ced565b61135b60208b018b612f7e565b8281811061136b5761136b612e07565b905060200201602081019061138091906129f5565b60045f61138d8d80612f7e565b8581811061139d5761139d612e07565b90506020020160208101906113b291906129f5565b6001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508980602001906114049190612f7e565b8281811061141457611414612e07565b905060200201602081019061142991906129f5565b6001600160a01b031661143c8b80612f7e565b8381811061144c5761144c612e07565b905060200201602081019061146191906129f5565b6001600160a01b03167f5f6921933580ca0adbbb669ff049927ba73230114570507fc8e10f0758f1d80460405160405180910390a36001016111f7565b506114af60608a0160408b016129f5565b5f80546001600160a01b0319166001600160a01b03929092169190911790556114de60808a0160608b016129f5565b600180546001600160a01b0319166001600160a01b039290921691909117905561150e60a08a0160808b016129f5565b600280546001600160a01b0319166001600160a01b039290921691909117905561153e60c08a0160a08b016129f5565b600380546001600160a01b0319166001600160a01b03929092169190911790556115706101808a016101608b016129f5565b600580546001600160a01b0319166001600160a01b03929092169190911790556115a26101a08a016101808b016129f5565b600680546001600160a01b0319166001600160a01b039283161790556005546040805163183fc7c960e31b81529051919092169163c1fe3e489160048083019260209291908290030181865afa1580156115fe573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116229190612e51565b600880546001600160a01b0319166001600160a01b03928316179055600654604080516338d52e0f60e01b8152905191909216916338d52e0f9160048083019260209291908290030181865afa15801561167e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116a29190612e51565b600780546001600160a01b0319166001600160a01b0392909216919091179055831561170857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b61171c826107f0565b61172581611c01565b610af48383611c0b565b5f805160206131ca83398151915261174681611c01565b61174e611c84565b5f5b828110156117a7575f84848381811061176b5761176b612e07565b905060200281019061177d9190612fc3565b61178690612fe1565b905061179e815f015182602001518360400151611cbb565b50600101611750565b50610b2d60015f805160206131aa83398151915255565b6003546040805163a1174e7d60e01b815290515f926001600160a01b03169163a1174e7d91600480830192869291908290030181865afa158015611804573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261182b9190810190612ef5565b80519091505f80806001600160a01b03861661185e576001600160a01b038088165f908152600460205260409020541695505b5f5b84811015611a0d575f86828151811061187b5761187b612e07565b6020908102919091010151604051630aa794bf60e31b81526001600160a01b0380831660048301529192509089169063553ca5f890602401602060405180830381865afa1580156118ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118f29190612e1b565b6118fc9086612e32565b604051639477e60b60e01b81526001600160a01b038a811660048301528b811660248301529196505f91829190841690639477e60b906044016040805180830381865afa15801561194f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611973919061306c565b909250905081156119f257604051637a8b263760e01b8152600481018390526001600160a01b038b1690637a8b263790602401602060405180830381865afa1580156119c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119e59190612e1b565b6119ef9087612e32565b95505b6119fc8186612e32565b945050600190920191506118609050565b505f6040518060400160405280611a2e8587611a299190612e32565b61274b565b6001600160801b03168152602001611a458461274b565b6001600160801b039081169091526001600160a01b0389165f908152600b6020908152604091829020825180840190935254808416808452600160801b90910484169183019190915283519394509092909116141580611abf575081602001516001600160801b031681602001516001600160801b031614155b15611708576001600160a01b038881165f818152600b60209081526040918290208651878301516001600160801b03908116600160801b81029190921690811790925583518c81529283019190915281830152905191928c16917f171c590e6e117d35af96b5ef519ca93014d4004dabd111d705c35158a92c88af9181900360600190a3505050505050505050565b611b56612782565b611b5e6127cb565b565b5f5f8051602061318a833981519152611b798484610eb7565b611bf8575f848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055611bae3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610622565b5f915050610622565b61064d81336127d3565b5f5f8051602061318a833981519152611c248484610eb7565b15611bf8575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610622565b5f805160206131aa833981519152805460011901611cb557604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b81518151808214611ce9576040516355c5b3e360e11b81526004810183905260248101829052604401610ced565b600354604051630735424b60e11b8152600481018790525f916001600160a01b031690630e6a849690602401602060405180830381865afa158015611d30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d549190612e51565b90506001600160a01b038116611d8057604051630fd3716f60e01b815260048101879052602401610ced565b5f836001600160401b03811115611d9957611d99612b6e565b604051908082528060200260200182016040528015611dc2578160200160208202803683370190505b5090505f5b84811015611eba575f878281518110611de257611de2612e07565b60200260200101519050868281518110611dfe57611dfe612e07565b60200260200101515f03611e4257868281518110611e1e57611e1e612e07565b602002602001015160405163fdea5f4d60e01b8152600401610ced91815260200190565b6001600160a01b038082165f908152600460205260409020541680611e8557604051634234b21b60e11b81526001600160a01b0383166004820152602401610ced565b80848481518110611e9857611e98612e07565b6001600160a01b03909216602092830291909101909101525050600101611dc7565b505f5460405163071794d960e31b81526001600160a01b03909116906338bca6c890611eec90899089906004016130c6565b5f604051808303815f87803b158015611f03575f80fd5b505af1158015611f15573d5f803e3d5ffd5b505050505f846001600160401b03811115611f3257611f32612b6e565b604051908082528060200260200182016040528015611f5b578160200160208202803683370190505b5090505f846001600160401b03811115611f7757611f77612b6e565b604051908082528060200260200182016040528015611fa0578160200160208202803683370190505b50600a549091506001600160a01b03165f5b878110156121305761200a828a8381518110611fd057611fd0612e07565b60200260200101518c8481518110611fea57611fea612e07565b60200260200101516001600160a01b03166128109092919063ffffffff16565b5f80836001600160a01b0316637647691d8c858151811061202d5761202d612e07565b60200260200101518e868151811061204757612047612e07565b60200260200101516040518363ffffffff1660e01b815260040161207e9291909182526001600160a01b0316602082015260400190565b60408051808303815f875af1158015612099573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120bd91906130f3565b91509150808684815181106120d4576120d4612e07565b60200260200101906001600160a01b031690816001600160a01b0316815250508185848151811061210757612107612e07565b60209081029190910101526121266001600160a01b03821689846128cd565b5050600101611fb2565b50897f73aaca990b709624ed7bf23319e478279075f1941e8b6546adedb985d67979b98a8a6040516121639291906130c6565b60405180910390a260405163b778bf7b60e01b81526001600160a01b0386169063b778bf7b9061219b90869086908990600401613116565b5f604051808303815f87803b1580156121b2575f80fd5b505af11580156121c4573d5f803e3d5ffd5b505050505f5b878110156121ef576121e78a8281518110610a6f57610a6f612e07565b6001016121ca565b507f94baf291029a59fe5651fb679bc5b38c0924cda9db75126bc7ec9e84bf5b1c2e83838660405161222393929190613116565b60405180910390a150505050505050505050565b60015f805160206131aa83398151915255565b6001600160a01b038281165f818152600460208190526040808320549051639477e60b60e01b81529085169181018290526024810193909352909290918391829190861690639477e60b906044016040805180830381865afa1580156122b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d6919061306c565b600a54604051637a8b263760e01b8152600481018490529294509092505f916001600160a01b039182169163db7711c6918a91881690637a8b263790602401602060405180830381865afa158015612330573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123549190612e1b565b604051630aa794bf60e31b81526001600160a01b038b8116600483015289169063553ca5f890602401602060405180830381865afa158015612398573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123bc9190612e1b565b6123c69190612e32565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa15801561240d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124319190612e1b565b905061243d8282612e32565b6124479086612e32565b979650505050505050565b5f61246560408301356020840135612e32565b600354604051630735424b60e11b8152843560048201529192505f916001600160a01b0390911690630e6a849690602401602060405180830381865afa1580156124b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124d59190612e51565b90506001600160a01b038116636919722e6124f660808601606087016129f5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044015f604051808303815f87803b15801561253b575f80fd5b505af115801561254d573d5f803e3d5ffd5b5050505060208301351561260f575f546001600160a01b031661258f81602086013561257f60808801606089016129f5565b6001600160a01b03169190612810565b6001600160a01b038116636c401b9e60208601356125b360808801606089016129f5565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044015f604051808303815f87803b1580156125f7575f80fd5b505af1158015612609573d5f803e3d5ffd5b50505050505b6040830135156126be576009546001600160a01b031661263e81604086013561257f60808801606089016129f5565b6001600160a01b038116636e553f65604086013561266260808801606089016129f5565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044015f604051808303815f87803b1580156126a6575f80fd5b505af11580156126b8573d5f803e3d5ffd5b50505050505b6126d76126d160808501606086016129f5565b5f6117be565b6126e760808401606085016129f5565b6001600160a01b0316835f01357f3f6bebd36732d678205582550aafcd5f10257e5d81c2aedf4cde45a8d0da79e785602001358660400135604051612736929190918252602082015260400190565b60405180910390a3505050565b611b5e612782565b5f6001600160801b0382111561277e576040516306dfcc6560e41b81526080600482015260248101839052604401610ced565b5090565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611b5e57604051631afcd79f60e31b815260040160405180910390fd5b612237612782565b6127dd8282610eb7565b61280c5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610ced565b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261286184826128fe565b610af4576040516001600160a01b0384811660248301525f60448301526128c391869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612947565b610af48482612947565b6040516001600160a01b03838116602483015260448201839052610b2d91859182169063a9059cbb90606401612891565b5f805f8060205f8651602088015f8a5af192503d91505f51905082801561293d5750811561292f578060011461293d565b5f866001600160a01b03163b115b9695505050505050565b5f8060205f8451602086015f885af180612966576040513d5f823e3d81fd5b50505f513d9150811561297d57806001141561298a565b6001600160a01b0384163b155b15610af457604051635274afe760e01b81526001600160a01b0385166004820152602401610ced565b5f602082840312156129c3575f80fd5b81356001600160e01b0319811681146129da575f80fd5b9392505050565b6001600160a01b038116811461064d575f80fd5b5f60208284031215612a05575f80fd5b81356129da816129e1565b5f8083601f840112612a20575f80fd5b5081356001600160401b03811115612a36575f80fd5b6020830191508360208260051b8501011115612a50575f80fd5b9250929050565b5f8060208385031215612a68575f80fd5b82356001600160401b03811115612a7d575f80fd5b612a8985828601612a10565b90969095509350505050565b5f815180845260208085019450602084015f5b83811015612ac457815187529582019590820190600101612aa8565b509495945050505050565b602081525f6129da6020830184612a95565b5f60208284031215612af1575f80fd5b5035919050565b5f805f60608486031215612b0a575f80fd5b8335612b15816129e1565b92506020840135612b25816129e1565b91506040840135612b35816129e1565b809150509250925092565b5f8060408385031215612b51575f80fd5b823591506020830135612b63816129e1565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612baa57612baa612b6e565b604052919050565b5f6001600160401b03821115612bca57612bca612b6e565b5060051b60200190565b5f82601f830112612be3575f80fd5b81356020612bf8612bf383612bb2565b612b82565b8083825260208201915060208460051b870101935086841115612c19575f80fd5b602086015b84811015612c3e578035612c31816129e1565b8352918301918301612c1e565b509695505050505050565b5f82601f830112612c58575f80fd5b81356020612c68612bf383612bb2565b8083825260208201915060208460051b870101935086841115612c89575f80fd5b602086015b84811015612c3e5780358352918301918301612c8e565b5f805f60608486031215612cb7575f80fd5b8335925060208401356001600160401b0380821115612cd4575f80fd5b612ce087838801612bd4565b93506040860135915080821115612cf5575f80fd5b50612d0286828701612c49565b9150509250925092565b5f8060408385031215612d1d575f80fd5b8235612d28816129e1565b91506020830135612b63816129e1565b5f8060208385031215612d49575f80fd5b82356001600160401b0380821115612d5f575f80fd5b818501915085601f830112612d72575f80fd5b813581811115612d80575f80fd5b8660208260071b8501011115612d94575f80fd5b60209290920196919550909350505050565b5f8060408385031215612db7575f80fd5b8235612dc2816129e1565b946020939093013593505050565b5f60208284031215612de0575f80fd5b81356001600160401b03811115612df5575f80fd5b82016101a081850312156129da575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612e2b575f80fd5b5051919050565b8082018082111561062257634e487b7160e01b5f52601160045260245ffd5b5f60208284031215612e61575f80fd5b81516129da816129e1565b5f6020808385031215612e7d575f80fd5b82516001600160401b03811115612e92575f80fd5b8301601f81018513612ea2575f80fd5b8051612eb0612bf382612bb2565b81815260059190911b82018301908381019087831115612ece575f80fd5b928401925b82841015612447578351612ee6816129e1565b82529284019290840190612ed3565b5f6020808385031215612f06575f80fd5b82516001600160401b03811115612f1b575f80fd5b8301601f81018513612f2b575f80fd5b8051612f39612bf382612bb2565b81815260059190911b82018301908381019087831115612f57575f80fd5b928401925b82841015612447578351612f6f816129e1565b82529284019290840190612f5c565b5f808335601e19843603018112612f93575f80fd5b8301803591506001600160401b03821115612fac575f80fd5b6020019150600581901b3603821315612a50575f80fd5b5f8235605e19833603018112612fd7575f80fd5b9190910192915050565b5f60608236031215612ff1575f80fd5b604051606081016001600160401b03828210818311171561301457613014612b6e565b8160405284358352602085013591508082111561302f575f80fd5b61303b36838701612bd4565b60208401526040850135915080821115613053575f80fd5b5061306036828601612c49565b60408301525092915050565b5f806040838503121561307d575f80fd5b505080516020909101519092909150565b5f815180845260208085019450602084015f5b83811015612ac45781516001600160a01b0316875295820195908201906001016130a1565b604081525f6130d8604083018561308e565b82810360208401526130ea8185612a95565b95945050505050565b5f8060408385031215613104575f80fd5b825191506020830151612b63816129e1565b606081525f613128606083018661308e565b6020838203602085015261313c8287612a95565b8481036040860152855180825260208088019450909101905f5b8181101561317b5784516001600160a01b031683529383019391830191600101613156565b50909897505050505050505056fe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00d804c5bf32ccb7c8f087c7a3be22668464f9b4302aec069f690a2c9ba96fc026a26469706673582212207daefa234f6af5e252abdc5c78bdce658e831c2056cb98ab259e57cc603c682264736f6c63430008180033", + "nonce": "0xec", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xafb56c825dfb11036963bdd704ccb76a053b172ca8af7c24fe51d2290890bec6", + "transactionType": "CREATE", + "contractName": "TokenStakingNode", + "contractAddress": "0xc602682b9ebc9719181b7a2b2479291cba26f801", + "function": null, + "arguments": null, + "transaction": { + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "gas": "0x2893e3", + "value": "0x0", + "input": "0x608060405234801561000f575f80fd5b5061001861001d565b6100cf565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006d5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cc5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61238380620000dd5f395ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80637c0867af11610088578063b3c6501511610063578063b3c65015146101d4578063b778bf7b146101f5578063d7b1041214610208578063dc560c8814610228575f80fd5b80637c0867af1461019257806392ab89bb146101a45780639477e60b146101ac575f80fd5b80635d21e3da116100c35780635d21e3da1461013a5780636919722e1461014d5780636ef610921461016057806377b349271461017f575f80fd5b8063139d7fed146100e95780632e4e7b72146101055780635c60da1b1461011a575b5f80fd5b6100f260015481565b6040519081526020015b60405180910390f35b610118610113366004611b3b565b610247565b005b610122610b0b565b6040516001600160a01b0390911681526020016100fc565b610118610148366004611c1c565b610bad565b61011861015b366004611cf7565b610d50565b6100f261016e366004611d21565b60036020525f908152604090205481565b61011861018d366004611d43565b610e5d565b5f54610122906001600160a01b031681565b610118610fbc565b6101bf6101ba366004611d7b565b611155565b604080519283526020830191909152016100fc565b6101dc611186565b60405167ffffffffffffffff90911681526020016100fc565b610118610203366004611df3565b6111be565b61021b610216366004611cf7565b611495565b6040516100fc9190611ec0565b6100f2610236366004611d21565b60026020525f908152604090205481565b5f8054906101000a90046001600160a01b03166001600160a01b03166352f94f986040518163ffffffff1660e01b8152600401602060405180830381865afa158015610295573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b99190611ed2565b604051630dc3e02960e01b81523360048201526001600160a01b039190911690630dc3e02990602401602060405180830381865afa1580156102fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103219190611eed565b61033e5760405163ddf2ac0960e01b815260040160405180910390fd5b5f805f9054906101000a90046001600160a01b03166001600160a01b031663ea4d3c9b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561038e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103b29190611ed2565b6040805160018082528183019092529192505f9190816020015b6104286040518060e001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f63ffffffff16815260200160608152602001606081525090565b8152602001906001900390816103cc5750506040805160018082528183019092529192505f91906020808301908036833701905050905085815f8151811061047257610472611f08565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f9181602001602082028036833701905050905087815f815181106104c1576104c1611f08565b6020908102919091018101919091526040805160e081018252308082529151631976849960e21b81526004810192909252918201906001600160a01b038716906365da126490602401602060405180830381865afa158015610525573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105499190611ed2565b6001600160a01b03168152602001306001600160a01b031681526020018b81526020018a63ffffffff16815260200183815260200182815250835f8151811061059457610594611f08565b602002602001018190525050505f856001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106029190611ed2565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610649573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061066d9190611f1c565b6040805160018082528183019092529192505f9190602080830190803683370190505090506001815f815181106106a6576106a6611f08565b911515602092830291909101909101526040805160018082528183019092525f91816020015b60608152602001906001900390816106cc5750506040805160018082528183019092529192506020808301908036833701905050815f8151811061071257610712611f08565b602002602001018190525083815f8151811061073057610730611f08565b60200260200101515f8151811061074957610749611f08565b6001600160a01b0392831660209182029290920101526040516319a021cb60e11b81529087169063334043969061078a90889085908d908890600401612020565b5f604051808303815f87803b1580156107a1575f80fd5b505af11580156107b3573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f94508593506001600160a01b03871692506370a082319150602401602060405180830381865afa1580156107ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108239190611f1c565b61082d9190612143565b90505f805f9054906101000a90046001600160a01b03166001600160a01b03166352f94f986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561087f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a39190611ed2565b6001600160a01b031663ac210cc76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108de573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109029190611ed2565b90506109186001600160a01b03851682846117ef565b604051629dd64160e51b8152600481018390526001600160a01b0385811660248301528216906313bac8209060440160408051808303815f875af1158015610962573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109869190612156565b6001600160a01b038b165f90815260026020526040812080549297509294508c92916109b3908490612143565b90915550506001600160a01b0384165f90815260036020526040812080548492906109df908490612179565b90915550508615610ab5575f8054906101000a90046001600160a01b03166001600160a01b03166352f94f986040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a38573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a5c9190611ed2565b6040516302a0964360e21b81526001600160a01b0386811660048301529190911690630a82590c906024015f604051808303815f87803b158015610a9e575f80fd5b505af1158015610ab0573d5f803e3d5ffd5b505050505b604080518b8152602081018490526001600160a01b038b168183015290517f4b31f68e60558505ff5dc8175085fba3a02ba8464fb0d1b68d08b1f32cf20c389181900360600190a1505050505050505050505050565b5f80610b3860017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d51612143565b5f1b90505f815490505f819050806001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b81573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba59190611ed2565b935050505090565b5f5460405163ce8572d360e01b81523360048201526001600160a01b039091169063ce8572d390602401602060405180830381865afa158015610bf2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c169190611eed565b610c3357604051636e10383f60e11b815260040160405180910390fd5b5f805f9054906101000a90046001600160a01b03166001600160a01b031663ea4d3c9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca79190611ed2565b60405163eea9064b60e01b81529091506001600160a01b0382169063eea9064b90610cda9087908790879060040161218c565b5f604051808303815f87803b158015610cf1575f80fd5b505af1158015610d03573d5f803e3d5ffd5b50505050836001600160a01b03167fa6ca69be1634c9486160d4fa9f11c9bf604a6a4b1fd23c8336ffc5889ef4b5ab83604051610d4291815260200190565b60405180910390a250505050565b5f5460405163e6319b4160e01b81523360048201526001600160a01b039091169063e6319b4190602401602060405180830381865afa158015610d95573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db99190611eed565b610dd6576040516308e8994960e11b815260040160405180910390fd5b6001600160a01b0382165f9081526003602052604081208054839290610dfd908490612143565b90915550610e1790506001600160a01b03831633836118b2565b604080518281526001600160a01b03841660208201527f75e9ac888aa93dea6ed455833591f43439ebd92d931d29877cbd162d0142e5c591015b60405180910390a15050565b80516001600160a01b038116610e865760405163d92e233d60e01b815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f81158015610ecb5750825b90505f8267ffffffffffffffff166001148015610ee75750303b155b905081158015610ef5575080155b15610f135760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610f3d57845460ff60401b1916600160401b1785555b610f456118e8565b86515f80546001600160a01b0319166001600160a01b0390921691909117905560208701516001558315610fb357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f5460405163ce8572d360e01b81523360048201526001600160a01b039091169063ce8572d390602401602060405180830381865afa158015611001573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110259190611eed565b61104257604051636e10383f60e11b815260040160405180910390fd5b5f805f9054906101000a90046001600160a01b03166001600160a01b031663ea4d3c9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b69190611ed2565b6040516336a2fa1960e21b81523060048201529091505f906001600160a01b0383169063da8be864906024015f604051808303815f875af11580156110fd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526111249190810190612203565b90507fffbd194689c4814f1672a47eaea1dd48a269b4b60b24c6d991dfe771cae1396081604051610e519190611ec0565b6001600160a01b038083165f90815260026020908152604080832054938516835260039091529020545b9250929050565b5f6111b97ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005467ffffffffffffffff1690565b905090565b6111c66118fa565b5f5460405163e6319b4160e01b81523360048201526001600160a01b039091169063e6319b4190602401602060405180830381865afa15801561120b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061122f9190611eed565b61124c576040516308e8994960e11b815260040160405180910390fd5b84838114158061125c5750808214155b1561127a5760405163512509d360e11b815260040160405180910390fd5b5f805f9054906101000a90046001600160a01b03166001600160a01b03166339b70e386040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112ca573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ee9190611ed2565b90505f5b82811015611461575f89898381811061130d5761130d611f08565b90506020020160208101906113229190611d21565b90505f88888481811061133757611337611f08565b9050602002013590505f87878581811061135357611353611f08565b90506020020160208101906113689190611d21565b905061137e6001600160a01b03841686846117ef565b6040516373d0285560e11b81526001600160a01b0382811660048301528481166024830152604482018490525f919087169063e7a050aa906064016020604051808303815f875af11580156113d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113f99190611f1c565b9050816001600160a01b0316846001600160a01b03167f501f0f7b8b32b1cd5e7b146b296f6118bd16a0575a150d8d19505dfd54fcbfe68584604051611449929190918252602082015260400190565b60405180910390a35050600190920191506112f29050565b50505061148d60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050505050565b5f5460408051630a5f29f360e31b815290516060926001600160a01b0316916352f94f989160048083019260209291908290030181865afa1580156114dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115009190611ed2565b604051630dc3e02960e01b81523360048201526001600160a01b039190911690630dc3e02990602401602060405180830381865afa158015611544573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115689190611eed565b6115855760405163ddf2ac0960e01b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833701905050905083815f815181106115b9576115b9611f08565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f9181602001602082028036833701905050905083815f8151811061160857611608611f08565b60209081029190910101526040805160018082528183019092525f91816020015b604080516060808201835280825260208201525f918101919091528152602001906001900390816116295790505090506040518060600160405280848152602001838152602001306001600160a01b0316815250815f8151811061168f5761168f611f08565b60200260200101819052508460025f886001600160a01b03166001600160a01b031681526020019081526020015f205f8282546116cc9190612179565b90915550505f546040805163ea4d3c9b60e01b815290516001600160a01b039092169163ea4d3c9b916004808201926020929091908290030181865afa158015611718573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061173c9190611ed2565b6001600160a01b0316630dd8dd02826040518263ffffffff1660e01b81526004016117679190612284565b5f604051808303815f875af1158015611782573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526117a99190810190612203565b93507f6cd4c0d874816de8d0b6d7b52dfa74c995531c24bb6834a0fb595309bc7987278686866040516117de9392919061231e565b60405180910390a150505092915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611840848261196a565b6118ac576040516001600160a01b0384811660248301525f60448301526118a291869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506119b5565b6118ac84826119b5565b50505050565b6040516001600160a01b038381166024830152604482018390526118e391859182169063a9059cbb90606401611870565b505050565b6118f0611a25565b6118f8611a6e565b565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0080546001190161193e57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f805f8060205f8651602088015f8a5af192503d91505f5190508280156119a95750811561199b57806001146119a9565b5f866001600160a01b03163b115b93505050505b92915050565b5f8060205f8451602086015f885af1806119d4576040513d5f823e3d81fd5b50505f513d915081156119eb5780600114156119f8565b6001600160a01b0384163b155b156118ac57604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166118f857604051631afcd79f60e31b815260040160405180910390fd5b611944611a25565b6001600160a01b0381168114611a8a575f80fd5b50565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611ac457611ac4611a8d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611af357611af3611a8d565b604052919050565b5f67ffffffffffffffff821115611b1457611b14611a8d565b5060051b60200190565b8015158114611a8a575f80fd5b8035611b3681611b1e565b919050565b5f805f805f8060c08789031215611b50575f80fd5b8635955060208088013563ffffffff81168114611b6b575f80fd5b9550604088013594506060880135611b8281611a76565b9350608088013567ffffffffffffffff811115611b9d575f80fd5b8801601f81018a13611bad575f80fd5b8035611bc0611bbb82611afb565b611aca565b81815260059190911b8201830190838101908c831115611bde575f80fd5b928401925b82841015611bfc57833582529284019290840190611be3565b8096505050505050611c1060a08801611b2b565b90509295509295509295565b5f805f60608486031215611c2e575f80fd5b8335611c3981611a76565b925060208481013567ffffffffffffffff80821115611c56575f80fd5b9086019060408289031215611c69575f80fd5b611c71611aa1565b823582811115611c7f575f80fd5b8301601f81018a13611c8f575f80fd5b803583811115611ca157611ca1611a8d565b611cb3601f8201601f19168701611aca565b93508084528a86828401011115611cc8575f80fd5b80868301878601375f908401860152509081529082013591810191909152929592945050506040919091013590565b5f8060408385031215611d08575f80fd5b8235611d1381611a76565b946020939093013593505050565b5f60208284031215611d31575f80fd5b8135611d3c81611a76565b9392505050565b5f60408284031215611d53575f80fd5b611d5b611aa1565b8235611d6681611a76565b81526020928301359281019290925250919050565b5f8060408385031215611d8c575f80fd5b8235611d9781611a76565b91506020830135611da781611a76565b809150509250929050565b5f8083601f840112611dc2575f80fd5b50813567ffffffffffffffff811115611dd9575f80fd5b6020830191508360208260051b850101111561117f575f80fd5b5f805f805f8060608789031215611e08575f80fd5b863567ffffffffffffffff80821115611e1f575f80fd5b611e2b8a838b01611db2565b90985096506020890135915080821115611e43575f80fd5b611e4f8a838b01611db2565b90965094506040890135915080821115611e67575f80fd5b50611e7489828a01611db2565b979a9699509497509295939492505050565b5f815180845260208085019450602084015f5b83811015611eb557815187529582019590820190600101611e99565b509495945050505050565b602081525f611d3c6020830184611e86565b5f60208284031215611ee2575f80fd5b8151611d3c81611a76565b5f60208284031215611efd575f80fd5b8151611d3c81611b1e565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611f2c575f80fd5b5051919050565b5f815180845260208085019450602084015f5b83811015611eb55781516001600160a01b031687529582019590820190600101611f46565b5f82825180855260208086019550808260051b8401018186015f5b84811015611fe257858303601f190189528151805180855290850190858501905f5b81811015611fcd5783516001600160a01b031683529287019291870191600101611fa8565b50509985019993505090830190600101611f86565b5090979650505050505050565b5f815180845260208085019450602084015f5b83811015611eb5578151151587529582019590820190600101612002565b5f60808083016080845280885180835260a0925060a08601915060a08160051b8701016020808c015f5b848110156120e557898403609f19018652815180516001600160a01b0390811686528482015181168587015260408083015190911690860152606080820151908601528881015163ffffffff16898601528781015160e0898701819052906120b482880182611f33565b91505060c080830151925086820381880152506120d18183611e86565b97850197955050509082019060010161204a565b5050878203908801526120f8818b611f6b565b94505050505082810360408401526121108186611e86565b905082810360608401526121248185611fef565b979650505050505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156119af576119af61212f565b5f8060408385031215612167575f80fd5b825191506020830151611da781611a76565b808201808211156119af576119af61212f565b60018060a01b03841681525f60206060602084015284516040606085015280518060a08601525f5b818110156121d05782810184015186820160c0015283016121b4565b505f60c082870101526020870151608086015260c0601f19601f8301168601019350505050826040830152949350505050565b5f6020808385031215612214575f80fd5b825167ffffffffffffffff81111561222a575f80fd5b8301601f8101851361223a575f80fd5b8051612248611bbb82611afb565b81815260059190911b82018301908381019087831115612266575f80fd5b928401925b828410156121245783518252928401929084019061226b565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b8381101561231057603f198984030185528151606081518186526122d182870182611f33565b915050888201518582038a8701526122e98282611e86565b928901516001600160a01b03169589019590955250948701949250908601906001016122ab565b509098975050505050505050565b60018060a01b0384168152826020820152606060408201525f6123446060830184611e86565b9594505050505056fea2646970667358221220d7e70ab54139b683ff97d83b6047827540783f7999bbb80602afa0d37c23f5ab64736f6c63430008180033", + "nonce": "0xed", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x86684a", + "logs": [ + { + "address": "0x9892a40fe6e17d4c88a92b2e37c12981baa6f14a", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x2febb0d22e189b6811f6ec5dc29462aed67c28db02adb663b6a2efa58cbbf022", + "transactionIndex": "0x71", + "logIndex": "0x9b", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000002000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x2febb0d22e189b6811f6ec5dc29462aed67c28db02adb663b6a2efa58cbbf022", + "transactionIndex": "0x71", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x1ae71b", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x9892a40fe6e17d4c88a92b2e37c12981baa6f14a" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x90552e", + "logs": [ + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000009892a40fe6e17d4c88a92b2e37c12981baa6f14a" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x66605fc4a78e1077605cce6d40694b602e195111db7d77976ea4de3072174ee8", + "transactionIndex": "0x72", + "logIndex": "0x9c", + "removed": false + }, + { + "address": "0xe5e91680fe69f508b92bdcbca2f867baaf58babb", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x66605fc4a78e1077605cce6d40694b602e195111db7d77976ea4de3072174ee8", + "transactionIndex": "0x72", + "logIndex": "0x9d", + "removed": false + }, + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5e91680fe69f508b92bdcbca2f867baaf58babb", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x66605fc4a78e1077605cce6d40694b602e195111db7d77976ea4de3072174ee8", + "transactionIndex": "0x72", + "logIndex": "0x9e", + "removed": false + } + ], + "logsBloom": "0x0000000000000000000000000000000040000000000000000080000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000000000200000100000000000000004000000000000000000002000000000000000000080000000080000000000000000090000040000000000000800000000000000000000000000000000000000000000080000000c000000000000000000000000000000000000000000000000000200800000000000020000000000000000000000000000000000400000000000000000020000000000000000000001000800000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x66605fc4a78e1077605cce6d40694b602e195111db7d77976ea4de3072174ee8", + "transactionIndex": "0x72", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x9ece4", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x73bc33999c34a5126ca19dc900f22690c288d55e" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc73a77", + "logs": [ + { + "address": "0xaac93a4dde34ce9ad9dd8556b9fadd83380a5d64", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xf6efd462bd99ad0841bcb0087ad440853c97da045dbe90f8d911605a3a0354a2", + "transactionIndex": "0x73", + "logIndex": "0x9f", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000001000000008000000", + "type": "0x0", + "transactionHash": "0xf6efd462bd99ad0841bcb0087ad440853c97da045dbe90f8d911605a3a0354a2", + "transactionIndex": "0x73", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x36e549", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0xaac93a4dde34ce9ad9dd8556b9fadd83380a5d64" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xd1275b", + "logs": [ + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000aac93a4dde34ce9ad9dd8556b9fadd83380a5d64" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa01662caef845b8b1812ffd5b114e679fe672a155c0e6fae8b9aa5d708c9a19a", + "transactionIndex": "0x74", + "logIndex": "0xa0", + "removed": false + }, + { + "address": "0xe612764d1986693f46e99605d274bbe28c3f03a7", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa01662caef845b8b1812ffd5b114e679fe672a155c0e6fae8b9aa5d708c9a19a", + "transactionIndex": "0x74", + "logIndex": "0xa1", + "removed": false + }, + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e612764d1986693f46e99605d274bbe28c3f03a7", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa01662caef845b8b1812ffd5b114e679fe672a155c0e6fae8b9aa5d708c9a19a", + "transactionIndex": "0x74", + "logIndex": "0xa2", + "removed": false + } + ], + "logsBloom": "0x00800000000000000000000000000000420000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000001000000000000000000000000000000000000020000000000000000000800000800800000000000000000100000400000000000000000000000000000000000001000000000000000000000800000004002000008000000000000000000000000000000000000000000200000000000000020000000000000000000000000000002000400000000000000000020000000000200000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0xa01662caef845b8b1812ffd5b114e679fe672a155c0e6fae8b9aa5d708c9a19a", + "transactionIndex": "0x74", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x9ece4", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x8face3283e20b19d98a7a132274b69c1304d60b4" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xdca819", + "logs": [ + { + "address": "0x7c31a924b01a20642af2460d7fe24a2fef89074d", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x92cbba922a78a2716be9f9739eb33381a09f7d725479e5406319aaf367af02dd", + "transactionIndex": "0x75", + "logIndex": "0xa3", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000040000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x92cbba922a78a2716be9f9739eb33381a09f7d725479e5406319aaf367af02dd", + "transactionIndex": "0x75", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0xb80be", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x7c31a924b01a20642af2460d7fe24a2fef89074d" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xe82c86", + "logs": [ + { + "address": "0x99db7619c018d61dbc2822767b63240d311d6992", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000007c31a924b01a20642af2460d7fe24a2fef89074d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa4", + "removed": false + }, + { + "address": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x00000000000000000000000099db7619c018d61dbc2822767b63240d311d6992", + "0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa5", + "removed": false + }, + { + "address": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x00000000000000000000000099db7619c018d61dbc2822767b63240d311d6992", + "0x000000000000000000000000dcee70654261af21c44c093c300ed3bb97b78192" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa6", + "removed": false + }, + { + "address": "0x99db7619c018d61dbc2822767b63240d311d6992", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa7", + "removed": false + }, + { + "address": "0x151057a14a4c84403e77c1fbc4f22a8156f63a4b", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000bb73f8a5b0074b27c6df026c77fa08b0111d017a" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa8", + "removed": false + }, + { + "address": "0x99db7619c018d61dbc2822767b63240d311d6992", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000151057a14a4c84403e77c1fbc4f22a8156f63a4b", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "logIndex": "0xa9", + "removed": false + } + ], + "logsBloom": "0x0000010008000020044000000000000040000000000000000080000000000000000000000000400000000000000000000100000008000000000000000020000000000000000000000000000000000200000100000000000000000000000000000000000002008000000000000820080000000080000400000800000010000040000000000000000000080000000000000000000000008000000000000080200002400000000000000000000000020000000000000000000000001020000000000000082020000800000000000000008000000000040c000000000000000420000010000000000000000000000000000000002000004000000000000000000000", + "type": "0x0", + "transactionHash": "0xa54895f69c148b187ebc44ad4f02fb4f638db97992d37bc97e3cb720b0ea62f6", + "transactionIndex": "0x76", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0xb846d", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x99db7619c018d61dbc2822767b63240d311d6992" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xeb76ac", + "logs": [ + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionIndex": "0x77", + "logIndex": "0xaa", + "removed": false + }, + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a", + "0x000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionIndex": "0x77", + "logIndex": "0xab", + "removed": false + }, + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a", + "0x000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionIndex": "0x77", + "logIndex": "0xac", + "removed": false + }, + { + "address": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionIndex": "0x77", + "logIndex": "0xad", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000010000800000000020000000000000000000800000000000000000000000000000000000000000000008000000800000000008000000000000080000000000001000000008000000000000000000000000000000000000000000000001000000000000000000000040000000000000000000020000000000004000100002000000020000000120000000000000000000000000000000400000000000000000000000000", + "type": "0x0", + "transactionHash": "0xbff796042eff46228f305bfceacb61f2390d0c3bd0931f976dcd22048afaa2a9", + "transactionIndex": "0x77", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x34a26", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": "0x73bc33999c34a5126ca19dc900f22690c288d55e", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xefe1cd", + "logs": [ + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "logIndex": "0xae", + "removed": false + }, + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x947478cb7f25f91a774cb9fce49ddd1952e530220912f89fefb6a8e0d8f04381", + "0x000000000000000000000000fcad670592a3b24869c0b51a6c6fded4f95d6975", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "logIndex": "0xaf", + "removed": false + }, + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x16e47d7ccdc4d9916471674b101198c830d9d6666d46998629b3ca840510386e", + "0x000000000000000000000000a08f39d30dc865cc11a49b6e5cbd27630d6141c3", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "logIndex": "0xb0", + "removed": false + }, + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x8586893ec6c8c067a87b0dc34e01d210b44bbdce9d41cb027cc2d7c0f31ead95", + "0x00000000000000000000000015519e68ca7544d1c919a2a6e9065375a1f0c80a", + "0x000000000000000000000000a1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d" + ], + "data": "0x", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "logIndex": "0xb1", + "removed": false + }, + { + "address": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "logIndex": "0xb2", + "removed": false + } + ], + "logsBloom": "0x00800004000000000000000040000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000040000000000000010000000000000000000000000008000000000000800800000004020000000000000000080800000800000000000000000000000000000000000000000000000800800000010000000020000080000000000000000000020002000000400000000000000000000000000000000000001000000000000000000000040000000000000000000000008000000004000101000000000020000000120000000000000000000000000000000000000000004000000000000000", + "type": "0x0", + "transactionHash": "0x75be36372e5a87e7c91c3a26f15812b975dc3213ec9f032d829ed23c2259fda9", + "transactionIndex": "0x78", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x46b21", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": "0x8face3283e20b19d98a7a132274b69c1304d60b4", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x113c93b", + "logs": [ + { + "address": "0x989c5e2509c501deb6195b9f525d9092514041b4", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xa4a1e959ec7c78baf4f7d509f72b0d04de335744dee26d1119caf5bb2bb0a205", + "transactionIndex": "0x79", + "logIndex": "0xb3", + "removed": false + } + ], + "logsBloom": "0x00000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0xa4a1e959ec7c78baf4f7d509f72b0d04de335744dee26d1119caf5bb2bb0a205", + "transactionIndex": "0x79", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x23e76e", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x989c5e2509c501deb6195b9f525d9092514041b4" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x12f9d69", + "logs": [ + { + "address": "0x94db8f0d5bbccebf6d8288d06eb53bb80ca125bd", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xe0562c7e3b23e3d02e4da2c337b2499b3aa4fb47b01166c18250738e0cbfd97e", + "transactionIndex": "0x7a", + "logIndex": "0xb4", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000008000000000800000000000000200000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0xe0562c7e3b23e3d02e4da2c337b2499b3aa4fb47b01166c18250738e0cbfd97e", + "transactionIndex": "0x7a", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x1bd42e", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x94db8f0d5bbccebf6d8288d06eb53bb80ca125bd" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14b1aba", + "logs": [ + { + "address": "0x81f34d0db58a7934549d9b2b1e76542ed9801b1f", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0x8df6e23b8b16c375e9a66a4e39b1d69ee3ed0cfe84afbc9bf32956fa5f4b1eb4", + "transactionIndex": "0x7b", + "logIndex": "0xb5", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000880000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000008000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x8df6e23b8b16c375e9a66a4e39b1d69ee3ed0cfe84afbc9bf32956fa5f4b1eb4", + "transactionIndex": "0x7b", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x1b7d51", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x81f34d0db58a7934549d9b2b1e76542ed9801b1f" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x15dd10d", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0xc231e03d016280344a8515fbc643c7a90bcb00510dd1568f0d539acb59c155e1", + "transactionIndex": "0x7c", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x12b653", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x8ef7a066bf2cf76bad826c1de8d314badf057b52" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x1896044", + "logs": [ + { + "address": "0x1776dea5799fc7ad10b6039f6e1927fefd731e85", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "transactionHash": "0xb22f97618e490063c02123570fd3bc8005735b9b5f63dc78c3e664462d6c9615", + "transactionIndex": "0x7d", + "logIndex": "0xb6", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000008000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000200000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0xb22f97618e490063c02123570fd3bc8005735b9b5f63dc78c3e664462d6c9615", + "transactionIndex": "0x7d", + "blockHash": "0xd7e0d790014f8f730f5912be6a3fb43fae8de0b63b2d041328aafd206cbc3479", + "blockNumber": "0x14117c8", + "gasUsed": "0x2b8f37", + "effectiveGasPrice": "0x2a23a332f", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0x1776dea5799fc7ad10b6039f6e1927fefd731e85" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x559edb", + "logs": [ + { + "address": "0xc602682b9ebc9719181b7a2b2479291cba26f801", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x80c1a57dad5aaa5a67d1e8e1eef21a39a9f5d448a612f9bda68871727e4e21ec", + "blockNumber": "0x14117fa", + "transactionHash": "0xafb56c825dfb11036963bdd704ccb76a053b172ca8af7c24fe51d2290890bec6", + "transactionIndex": "0x12", + "logIndex": "0x8b", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000", + "type": "0x0", + "transactionHash": "0xafb56c825dfb11036963bdd704ccb76a053b172ca8af7c24fe51d2290890bec6", + "transactionIndex": "0x12", + "blockHash": "0x80c1a57dad5aaa5a67d1e8e1eef21a39a9f5d448a612f9bda68871727e4e21ec", + "blockNumber": "0x14117fa", + "gasUsed": "0x1f36af", + "effectiveGasPrice": "0x286dd4de7", + "from": "0xa1e340bd1e3ea09b3981164bbb4afeddf0e7ba0d", + "to": null, + "contractAddress": "0xc602682b9ebc9719181b7a2b2479291cba26f801" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1729866898, + "chain": 1, + "commit": "156693d" +} \ No newline at end of file diff --git a/deployments/v0.0.3-ynEigenViewer-17000-4d0ed054af4e3877bc3f4dc7affd12c843d22f1b.json b/deployments/v0.0.3-ynEigenViewer-17000-4d0ed054af4e3877bc3f4dc7affd12c843d22f1b.json new file mode 100644 index 000000000..0ddc55b2a --- /dev/null +++ b/deployments/v0.0.3-ynEigenViewer-17000-4d0ed054af4e3877bc3f4dc7affd12c843d22f1b.json @@ -0,0 +1,51 @@ +{ + "transactions": [ + { + "hash": "0x6645dc197a9f650c593571384bf632b68982fc986dc0c750f4f9acd5c828f2e4", + "transactionType": "CREATE", + "contractName": "ynEigenViewer", + "contractAddress": "0xbea193a39958bc175b10cc1dfc742e5a3ebaafaf", + "function": null, + "arguments": [ + "0xaD31546AdbfE1EcD7137310508f112039a35b6F7", + "0x071bdC8eDcdD66730f45a3D3A6F794FAA37C75ED", + "0x5c20D1a85C7d9acB503135a498E26Eb55d806552", + "0xd68C29263F6dC2Ff8D9307b3AfAcD6D6fDeFbB3A" + ], + "transaction": { + "from": "0xd7d4a7f14265b0a69ae482b85b0a8496c3f99fb9", + "gas": "0x15c9de", + "value": "0x0", + "input": "0x61010060405234801562000011575f80fd5b506040516200143238038062001432833981016040819052620000349162000073565b6001600160a01b0393841660805291831660a052821660c0521660e052620000cd565b80516001600160a01b03811681146200006e575f80fd5b919050565b5f805f806080858703121562000087575f80fd5b620000928562000057565b9350620000a26020860162000057565b9250620000b26040860162000057565b9150620000c26060860162000057565b905092959194509250565b60805160a05160c05160e0516112de620001545f395f818161015d015261063b01525f8181610136015261076301525f818160ef015281816103a2015281816107ec0152818161086f0152818161093701528181610bee01528181610d110152610d6801525f8181610184015281816101cd015281816102e6015261044c01526112de5ff3fe608060405234801561000f575f80fd5b506004361061009b575f3560e01c80637c0867af116100635780637c0867af14610131578063949db65814610158578063979d7e861461017f5780639d8e2177146101a6578063b8f82b26146101b5575f80fd5b8063075c2b191461009f5780632e0f2625146100bd5780633ff36802146100d557806363f7bad5146100ea578063679aefce14610129575b5f80fd5b6100a76101c8565b6040516100b49190610e2c565b60405180910390f35b6100c7620f424081565b6040519081526020016100b4565b6100dd61075f565b6040516100b49190610ef0565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b4565b6100c76107e8565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6100c7670de0b6b3a764000081565b6100c76101c3366004610f53565b610933565b60605f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166367e4ac2c6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610226573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261024d9190810190610fe5565b80519091508067ffffffffffffffff81111561026b5761026b610f7d565b6040519080825280602002602001820160405280156102e057816020015b6102cd6040518060e001604052805f6001600160a01b0316815260200160608152602001606081526020015f81526020015f81526020015f81526020015f81525090565b8152602001906001900390816102895790505b5092505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663613e85ff6040518163ffffffff1660e01b81526004015f60405180830381865afa15801561033f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610366919081019061107f565b90508051821461039f578051604051631f4bb7c160e31b8152610396918491600401918252602082015260400190565b60405180910390fd5b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104209190611100565b90505f5b83811015610757575f83828151811061043f5761043f611117565b602002602001015190505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631cbf960d88858151811061048b5761048b611117565b6020026020010151846040518363ffffffff1660e01b81526004016104c59291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa1580156104e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105049190611100565b90506040518060e0016040528088858151811061052357610523611117565b60200260200101516001600160a01b0316815260200188858151811061054b5761054b611117565b60200260200101516001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa15801561058d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105b4919081019061112b565b81526020018885815181106105cb576105cb611117565b60200260200101516001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa15801561060d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610634919081019061112b565b81526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ba9d8ca8a878151811061067a5761067a611117565b60200260200101516040518263ffffffff1660e01b81526004016106ad91906001600160a01b0391909116815260200190565b602060405180830381865afa1580156106c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ec9190611100565b81526020015f831180156106ff57505f86115b610709575f610721565b85610717620f4240856111ba565b61072191906111dd565b81526020018281526020018381525088848151811061074257610742611117565b60209081029190910101525050600101610424565b505050505090565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a1174e7d6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156107bc573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107e391908101906111fc565b905090565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610846573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086a9190611100565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ed9190611100565b90508115806108fa575080155b1561090f57670de0b6b3a76400009250505090565b8161092282670de0b6b3a76400006111ba565b61092c91906111dd565b9250505090565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352f94f986040518163ffffffff1660e01b8152600401602060405180830381865afa158015610991573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b59190611286565b90505f816001600160a01b0316634e6c97666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a189190611286565b90505f826001600160a01b031663c1fe3e486040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a7b9190611286565b90505f836001600160a01b031663daba667d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610aba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ade9190611286565b90505f846001600160a01b0316634aa07e646040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b1d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b419190611286565b9050836001600160a01b0316886001600160a01b031603610c67576040516363737ac960e11b8152600481018890525f906001600160a01b0384169063c6e6f59290602401602060405180830381865afa158015610ba1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc59190611100565b604051635c7c159360e11b81526001600160a01b038581166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063b8f82b26906044015b602060405180830381865afa158015610c36573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5a9190611100565b9650505050505050610dd9565b826001600160a01b0316886001600160a01b031603610d425760405162b0e38960e81b8152600481018890525f906001600160a01b0383169063b0e3890090602401602060405180830381865afa158015610cc4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ce89190611100565b604051635c7c159360e11b81526001600160a01b038481166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063b8f82b2690604401610c1b565b604051635c7c159360e11b81526001600160a01b038981166004830152602482018990527f0000000000000000000000000000000000000000000000000000000000000000169063b8f82b2690604401602060405180830381865afa158015610dad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dd19190611100565b955050505050505b92915050565b5f5b83811015610df9578181015183820152602001610de1565b50505f910152565b5f8151808452610e18816020860160208601610ddf565b601f01601f19169290920160200192915050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015610ee257888303603f19018552815180516001600160a01b031684528781015160e089860181905290610e8c82870182610e01565b9150508782015185820389870152610ea48282610e01565b606084810151908801526080808501519088015260a0808501519088015260c093840151939096019290925250509386019390860190600101610e53565b509098975050505050505050565b602080825282518282018190525f9190848201906040850190845b81811015610f305783516001600160a01b031683529284019291840191600101610f0b565b50909695505050505050565b6001600160a01b0381168114610f50575f80fd5b50565b5f8060408385031215610f64575f80fd5b8235610f6f81610f3c565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610fba57610fba610f7d565b604052919050565b5f67ffffffffffffffff821115610fdb57610fdb610f7d565b5060051b60200190565b5f6020808385031215610ff6575f80fd5b825167ffffffffffffffff81111561100c575f80fd5b8301601f8101851361101c575f80fd5b805161102f61102a82610fc2565b610f91565b81815260059190911b8201830190838101908783111561104d575f80fd5b928401925b8284101561107457835161106581610f3c565b82529284019290840190611052565b979650505050505050565b5f6020808385031215611090575f80fd5b825167ffffffffffffffff8111156110a6575f80fd5b8301601f810185136110b6575f80fd5b80516110c461102a82610fc2565b81815260059190911b820183019083810190878311156110e2575f80fd5b928401925b82841015611074578351825292840192908401906110e7565b5f60208284031215611110575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561113b575f80fd5b815167ffffffffffffffff80821115611152575f80fd5b818401915084601f830112611165575f80fd5b81518181111561117757611177610f7d565b61118a601f8201601f1916602001610f91565b91508082528560208285010111156111a0575f80fd5b6111b1816020840160208601610ddf565b50949350505050565b8082028115828204841417610dd957634e487b7160e01b5f52601160045260245ffd5b5f826111f757634e487b7160e01b5f52601260045260245ffd5b500490565b5f602080838503121561120d575f80fd5b825167ffffffffffffffff811115611223575f80fd5b8301601f81018513611233575f80fd5b805161124161102a82610fc2565b81815260059190911b8201830190838101908783111561125f575f80fd5b928401925b8284101561107457835161127781610f3c565b82529284019290840190611264565b5f60208284031215611296575f80fd5b81516112a181610f3c565b939250505056fea2646970667358221220e13239e732eae37dd9a6fb584eb86ca47b27fbdc7f5b4ca923c907d0704f12f464736f6c63430008180033000000000000000000000000ad31546adbfe1ecd7137310508f112039a35b6f7000000000000000000000000071bdc8edcdd66730f45a3d3a6f794faa37c75ed0000000000000000000000005c20d1a85c7d9acb503135a498e26eb55d806552000000000000000000000000d68c29263f6dc2ff8d9307b3afacd6d6fdefbb3a", + "nonce": "0x177", + "chainId": "0x4268" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x2bb913", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6645dc197a9f650c593571384bf632b68982fc986dc0c750f4f9acd5c828f2e4", + "transactionIndex": "0x13", + "blockHash": "0x9014d974e965c1a7c95b79dc6b6381b0ce49b5ba682420eb76af13d53aed6a41", + "blockNumber": "0x23eec4", + "gasUsed": "0x10c2ab", + "effectiveGasPrice": "0xa301bb", + "from": "0xd7d4a7f14265b0a69ae482b85b0a8496c3f99fb9", + "to": null, + "contractAddress": "0xbea193a39958bc175b10cc1dfc742e5a3ebaafaf" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1726598187, + "chain": 17000, + "commit": "aedbbd9" +} \ No newline at end of file diff --git a/deployments/ynLSDe-17000-ynFoo.json b/deployments/ynLSDe-17000-ynFoo.json new file mode 100644 index 000000000..4a3d155f3 --- /dev/null +++ b/deployments/ynLSDe-17000-ynFoo.json @@ -0,0 +1,46 @@ +{ + "ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "DEFAULT_SIGNER": "0x72fdBD51085bDa5eEEd3b55D1a46E2e92f0837a5", + "EIGEN_STRATEGY_ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "PAUSE_ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "PROXY_ADMIN_OWNER": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "STAKING_ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "STAKING_NODES_OPERATOR": "0x9Dd8F69b62ddFd990241530F47dcEd0Dad7f7d39", + "STRATEGY_CONTROLLER": "0x1234567890123456789012345678901234567890", + "TOKEN_STAKING_NODE_CREATOR": "0x9Dd8F69b62ddFd990241530F47dcEd0Dad7f7d39", + "UNPAUSE_ADMIN": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "YNDev": "0x9Dd8F69b62ddFd990241530F47dcEd0Dad7f7d39", + "YnSecurityCouncil": "0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913", + "implementation-assetRegistry": "0x156e0382068C3f96a629f51dcF99cEA5250B9eda", + "implementation-eigenStrategyManager": "0x251D14a2FB3cf3E35CE2355fBC7943257bcCcA08", + "implementation-lsdWrapper": "0xD0F77441B70c84aa3366a9F79F2fD16618739aB0", + "implementation-rateProvider": "0x17969afC774ec28802F1316cd4474c537114600A", + "implementation-redemptionAssetsVault": "0xB510d24856795F4B7Bb6e977E14D3157Ceeaa7FE", + "implementation-tokenStakingNodesManager": "0xeD44B98Bd50cd5e128B420495bd9DA384A291B9A", + "implementation-withdrawalQueueManager": "0x108D8d8d89B3459ec37c0E71A51C8a6771aC488c", + "implementation-ynEigenDepositAdapter": "0x11830FF94221F2Ef34176AD85A6cCAa2f41C95fa", + "implementation-ynEigenViewer": "0xe30c24d5E6Cf5320a9ad550853b80d6e506fcb5b", + "implementation-ynLSDe": "0x552f4b850d4963D914E6B2C011B5FE475468d3B8", + "proxy-assetRegistry": "0x726cc095C893c2ff6d572C1B2F26e0Ed08484302", + "proxy-eigenStrategyManager": "0x6e18EfFF496b108522bdCF5db92e97c5EE8a2DEd", + "proxy-lsdWrapper": "0xb94FA8D53313b4B6c69DC20489C78E2AF54C5B61", + "proxy-rateProvider": "0x0E68FedE865158D7501e5Ce5033B4fca9123CA98", + "proxy-redemptionAssetsVault": "0xAF920e9D61b91e1b8e39AE6bFBa5Fa73C2f32A34", + "proxy-tokenStakingNodesManager": "0x8c1717166F02911960bD4A31A8C725909A2de39e", + "proxy-withdrawalQueueManager": "0x34354efDF0931d37020e7331363403930c9e251e", + "proxy-ynEigenDepositAdapter": "0x6196F39D95805Fc6186c191E640e8fad156633Ff", + "proxy-ynEigenViewer": "0xb80EecB2904DAd7410B3af6bE897E01dca8CF475", + "proxy-ynLSDe": "0x73961FEcac088A52DdCe286E6935b6bd9Bf391E5", + "proxyAdmin-assetRegistry": "0xBBD351d0137c2C5f44CB8FE1DF4f5398FC8711df", + "proxyAdmin-eigenStrategyManager": "0x44377f05b1b9521F10320319B01C2D781f624719", + "proxyAdmin-lsdWrapper": "0x0432DD28B89b28911b90808861E68885646B9E6E", + "proxyAdmin-rateProvider": "0x65b32cBEcfb849Aa6fD89e6DA1a894Ee7899acD7", + "proxyAdmin-redemptionAssetsVault": "0x890c0367eB82FF4114FcA95CdEbEbD12b61a2a9d", + "proxyAdmin-tokenStakingNodesManager": "0x5a153929A995950B72F4606dfAECb60fBDDaB4Af", + "proxyAdmin-withdrawalQueueManager": "0x84376C30FC35a69C22271ECBA4ca26037a2f8e4E", + "proxyAdmin-ynEigenDepositAdapter": "0x14a87CA41091ddBa399e41b4bC174330dF378dCE", + "proxyAdmin-ynEigenViewer": "0x121dAa9722E2C8e56C35693d7c6913fEd57D5552", + "proxyAdmin-ynLSDe": "0x1745fAAf07167B2D33DE831C1E4e3344090138b4", + "tokenStakingNodeImplementation": "0xc7Fb9046f1db5A36D635Ad1E70D425b779b29840", + "upgradeTimelock": "0x56664FFcCfF6BB282CcA96808AF03d9042e1f799" +} \ No newline at end of file diff --git a/script/Actors.sol b/script/Actors.sol index bfc69facf..57606526b 100644 --- a/script/Actors.sol +++ b/script/Actors.sol @@ -33,6 +33,9 @@ contract ActorAddresses { address STAKING_NODES_WITHDRAWER; address STRATEGY_CONTROLLER; address TOKEN_STAKING_NODE_OPERATOR; + address TOKEN_STAKING_NODES_WITHDRAWER; + address YNEIGEN_REQUEST_FINALIZER; + address YNEIGEN_WITHDRAWAL_MANAGER; } struct Wallets { @@ -44,6 +47,7 @@ contract ActorAddresses { address YNTokenStakingNodeOperator; address YNWithdrawalsETH; address YnOperator; + address YNnWithdrawalsYnEigen; } struct Actors { @@ -67,7 +71,8 @@ contract ActorAddresses { // TODO: replace with concrete deployment YNTokenStakingNodeOperator: 0x2234567890123456789012345678901234567890, YNWithdrawalsETH: 0x0e36E2bCD71059E02822DFE52cBa900730b07c07, - YnOperator: 0x530F6057e93b54Ec39D6472DA75712db2178780C + YnOperator: 0x530F6057e93b54Ec39D6472DA75712db2178780C, + YNnWithdrawalsYnEigen: 0xbc345A8aEd2ff40308Cf923216dF39B5bE1146b2 }); actors[17000] = Actors({ eoa: EOAActors({ @@ -99,7 +104,10 @@ contract ActorAddresses { WITHDRAWAL_MANAGER: holeskyWallets.YNWithdrawalsETH, REDEMPTION_ASSET_WITHDRAWER: holeskyWallets.YNDev, REQUEST_FINALIZER: holeskyWallets.YNWithdrawalsETH, - STAKING_NODES_WITHDRAWER: holeskyWallets.YNWithdrawalsETH + STAKING_NODES_WITHDRAWER: holeskyWallets.YNWithdrawalsETH, + TOKEN_STAKING_NODES_WITHDRAWER: holeskyWallets.YNnWithdrawalsYnEigen, + YNEIGEN_REQUEST_FINALIZER: holeskyWallets.YNnWithdrawalsYnEigen, + YNEIGEN_WITHDRAWAL_MANAGER: holeskyWallets.YNnWithdrawalsYnEigen }), wallets: holeskyWallets }); @@ -114,7 +122,8 @@ contract ActorAddresses { // TODO: replace with concrete deployment YNTokenStakingNodeOperator: 0xfcad670592a3b24869C0b51a6c6FDED4F95D6975, // same as YNSecurityCouncil YNWithdrawalsETH: 0x7f7187fbD6e508bC23268746dff535cfC8EbC87b, - YnOperator: 0x591A163AcfDb6F79674b08e5F069b4905a230ddD + YnOperator: 0x591A163AcfDb6F79674b08e5F069b4905a230ddD, + YNnWithdrawalsYnEigen: 0x15519e68Ca7544d1C919A2A6e9065375A1f0C80A }); actors[1] = Actors({ @@ -147,7 +156,10 @@ contract ActorAddresses { WITHDRAWAL_MANAGER: mainnetWallets.YNWithdrawalsETH, REDEMPTION_ASSET_WITHDRAWER: mainnetWallets.YNDev, REQUEST_FINALIZER: mainnetWallets.YNWithdrawalsETH, - STAKING_NODES_WITHDRAWER: mainnetWallets.YNWithdrawalsETH + STAKING_NODES_WITHDRAWER: mainnetWallets.YNWithdrawalsETH, + TOKEN_STAKING_NODES_WITHDRAWER: mainnetWallets.YNnWithdrawalsYnEigen, + YNEIGEN_REQUEST_FINALIZER: mainnetWallets.YNnWithdrawalsYnEigen, + YNEIGEN_WITHDRAWAL_MANAGER: mainnetWallets.YNnWithdrawalsYnEigen }), wallets: mainnetWallets }); diff --git a/script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol b/script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol index 6043210d5..83f94fccb 100644 --- a/script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol +++ b/script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol @@ -7,19 +7,62 @@ import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.s import {BaseYnEigenScript} from "script/ynEigen/BaseYnEigenScript.s.sol"; +/** + * @title GenerateYnLSDeUpgradeTxData + * @dev This script generates the transaction data needed to upgrade a specific contract in the YnLSDe system. + * + * USAGE: +* -------- + * To run this script, use the following command in your terminal: + * + * TOKEN=[token name] CONTRACT_TO_UPGRADE=[contract identifier] NEW_IMPLEMENTATION=[implementation address] forge script script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol --legacy --rpc-url [rpc url] + * + * + * Where: + * - TOKEN: The name of the token (e.g., ynLSDe) + * - CONTRACT_TO_UPGRADE: The name of the contract to be upgraded (e.g., rateProvider) + * - NEW_IMPLEMENTATION: The address of the new implementation contract + * + * + * + * EXAMPLE: + * -------- + * # Upgrade rateProvider of ynLSDe on Holesky to the given implementation + * TOKEN=ynLSDe CONTRACT_TO_UPGRADE=rateProvider NEW_IMPLEMENTATION=0x48c3dfd4d14e7899c4adbf8e2d5aef6af585d305 forge script script/upgrades/GenerateYnLSDeUpgradeTxData.s.sol --legacy --rpc-url https://rpc.ankr.com/eth_holesky + * + * This command will: + * 1. Set the token name to 'ynLSDe' + * 2. Specify 'rateProvider' as the contract to upgrade + * 3. Set the new implementation address to 0x48c3dfd4d14e7899c4adbf8e2d5aef6af585d305 + * 4. Use the Holesky testnet RPC URL for execution + * + * The script will then generate and display the necessary transaction data for the upgrade process. + * -------- + */ + contract GenerateYnLSDeUpgradeTxData is BaseYnEigenScript { Deployment deployment; + string internal _tokenName; + + function tokenName() internal view override returns (string memory) { + return _tokenName; + } + function run() external { - deployment = loadDeployment(); console.log("=== Upgrade Information ==="); console.log("Current Block Number: %s", block.number); console.log("Current Chain ID: %s", block.chainid); + _tokenName = vm.envString("TOKEN"); string memory contractToUpgrade = vm.envString("CONTRACT_TO_UPGRADE"); address newImplementation = vm.envAddress("NEW_IMPLEMENTATION"); + console.log("Token Name: %s", _tokenName); + + deployment = loadDeployment(); + console.log("=== Contract Upgrade Details ==="); console.log("Contract to upgrade: %s", contractToUpgrade); console.log("Contract address: %s", vm.toString(getProxyAddress(contractToUpgrade))); diff --git a/script/ynEigen/BaseYnEigenScript.s.sol b/script/ynEigen/BaseYnEigenScript.s.sol index a7af630b8..01ec3babb 100644 --- a/script/ynEigen/BaseYnEigenScript.s.sol +++ b/script/ynEigen/BaseYnEigenScript.s.sol @@ -10,6 +10,10 @@ import {TokenStakingNode} from "src/ynEIGEN/TokenStakingNode.sol"; import {ynEigenDepositAdapter} from "src/ynEIGEN/ynEigenDepositAdapter.sol"; import {IRateProvider} from "src/interfaces/IRateProvider.sol"; import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; +import {IWrapper} from "src/interfaces/IWrapper.sol"; import {ActorAddresses} from "script/Actors.sol"; import {ContractAddresses} from "script/ContractAddresses.sol"; @@ -30,6 +34,9 @@ contract BaseYnEigenScript is BaseScript { ProxyAddresses ynEigenDepositAdapter; ProxyAddresses rateProvider; ProxyAddresses ynEigenViewer; + ProxyAddresses redemptionAssetsVault; + ProxyAddresses withdrawalQueueManager; + ProxyAddresses wrapper; } struct Deployment { @@ -43,6 +50,9 @@ contract BaseYnEigenScript is BaseScript { TimelockController upgradeTimelock; ynEigenViewer viewer; DeploymentProxies proxies; + RedemptionAssetsVault redemptionAssetsVault; + WithdrawalQueueManager withdrawalQueueManager; + IWrapper wrapper; } struct Asset { @@ -99,7 +109,7 @@ contract BaseYnEigenScript is BaseScript { if (!isSupportedChainId(inputs.chainId)) revert UnsupportedChainId(inputs.chainId); } - function tokenName() internal view returns (string memory) { + function tokenName() internal virtual view returns (string memory) { return inputs.symbol; } @@ -107,6 +117,7 @@ contract BaseYnEigenScript is BaseScript { string memory root = vm.projectRoot(); return string.concat(root, "/deployments/", tokenName(), "-", vm.toString(block.chainid), ".json"); + // return string.concat(root, "/deployments/", tokenName(), "-", vm.toString(block.chainid), "-ynFoo", ".json"); } function saveDeployment(Deployment memory deployment) public virtual { @@ -122,6 +133,10 @@ contract BaseYnEigenScript is BaseScript { serializeProxyElements(json, "rateProvider", address(deployment.rateProvider)); serializeProxyElements(json, "ynEigenViewer", address(deployment.viewer)); vm.serializeAddress(json, "upgradeTimelock", address(deployment.upgradeTimelock)); + serializeProxyElements(json, "redemptionAssetsVault", address(deployment.redemptionAssetsVault)); + serializeProxyElements(json, "withdrawalQueueManager", address(deployment.withdrawalQueueManager)); + serializeProxyElements(json, "wrapper", address(deployment.wrapper)); + // actors vm.serializeAddress(json, "PROXY_ADMIN_OWNER", address(actors.admin.PROXY_ADMIN_OWNER)); @@ -175,6 +190,15 @@ contract BaseYnEigenScript is BaseScript { deployment.viewer = ynEigenViewer(payable(jsonContent.readAddress(".proxy-ynEigenViewer"))); proxies.ynEigenViewer = loadProxyAddresses(jsonContent, "ynEigenViewer"); + + deployment.redemptionAssetsVault = RedemptionAssetsVault(payable(jsonContent.readAddress(".proxy-redemptionAssetsVault"))); + proxies.redemptionAssetsVault = loadProxyAddresses(jsonContent, "redemptionAssetsVault"); + + deployment.withdrawalQueueManager = WithdrawalQueueManager(payable(jsonContent.readAddress(".proxy-withdrawalQueueManager"))); + proxies.withdrawalQueueManager = loadProxyAddresses(jsonContent, "withdrawalQueueManager"); + + deployment.wrapper = IWrapper(payable(jsonContent.readAddress(".proxy-wrapper"))); + proxies.wrapper = loadProxyAddresses(jsonContent, "wrapper"); deployment.upgradeTimelock = TimelockController(payable(jsonContent.readAddress(".upgradeTimelock"))); diff --git a/script/ynEigen/YnEigenDeployer.s.sol b/script/ynEigen/YnEigenDeployer.s.sol index 445ebbdd8..cbe40b35e 100644 --- a/script/ynEigen/YnEigenDeployer.s.sol +++ b/script/ynEigen/YnEigenDeployer.s.sol @@ -19,11 +19,14 @@ import {AssetRegistry} from "src/ynEIGEN/AssetRegistry.sol"; import {TokenStakingNodesManager} from "src/ynEIGEN/TokenStakingNodesManager.sol"; import {ynEigenDepositAdapter} from "src/ynEIGEN/ynEigenDepositAdapter.sol"; import {ynEigenViewer} from "src/ynEIGEN/ynEigenViewer.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; import {BaseYnEigenScript} from "script/ynEigen/BaseYnEigenScript.s.sol"; import {YnEigenFactory} from "./YnEigenFactory.sol"; -import {YnEigenInit, YnEigenActors, YnEigenChainAddresses, YnEigenImplementations} from "./YnEigenStructs.sol"; +import {YnEigenInit, YnEigenActors, YnEigenChainAddresses, YnEigenImplementations, YnEigenProxies} from "./YnEigenStructs.sol"; import {ynEigen} from "src/ynEIGEN/ynEigen.sol"; import {EigenStrategyManager} from "src/ynEIGEN/EigenStrategyManager.sol"; @@ -124,7 +127,15 @@ contract YnEigenDeployer is BaseYnEigenScript { tokenStakingNodesManager: address(new TokenStakingNodesManager()), tokenStakingNode: address(new TokenStakingNode()), assetRegistry: address(new AssetRegistry()), - depositAdapter: address(new ynEigenDepositAdapter()) + depositAdapter: address(new ynEigenDepositAdapter()), + redemptionAssetsVault: address(new RedemptionAssetsVault()), + withdrawalQueueManager: address(new WithdrawalQueueManager()), + lsdWrapper: address(new LSDWrapper( + chainAddresses.lsd.WSTETH_ADDRESS, + chainAddresses.lsd.WOETH_ADDRESS, + chainAddresses.lsd.OETH_ADDRESS, + chainAddresses.lsd.STETH_ADDRESS + )) }); } @@ -156,17 +167,7 @@ contract YnEigenDeployer is BaseYnEigenScript { { YnEigenFactory factory = new YnEigenFactory(); - ( - ynEigen ynToken, - EigenStrategyManager eigenStrategyManager, - TokenStakingNodesManager tokenStakingNodesManager, - TokenStakingNode tokenStakingNode, - AssetRegistry assetRegistry, - ynEigenDepositAdapter ynEigenDepositAdapterInstance, - IRateProvider rateProvider, - TimelockController timelock, - ynEigenViewer viewer - ) = factory.deploy(init); + YnEigenProxies memory proxies = factory.deploy(init); vm.stopBroadcast(); @@ -176,15 +177,18 @@ contract YnEigenDeployer is BaseYnEigenScript { address(0) ); Deployment memory deployment = Deployment({ - ynEigen: ynToken, - assetRegistry: assetRegistry, - eigenStrategyManager: eigenStrategyManager, - tokenStakingNodesManager: tokenStakingNodesManager, - tokenStakingNodeImplementation: tokenStakingNode, - ynEigenDepositAdapterInstance: ynEigenDepositAdapterInstance, - rateProvider: rateProvider, - upgradeTimelock: timelock, - viewer: viewer, + ynEigen: proxies.ynToken, + assetRegistry: proxies.assetRegistry, + eigenStrategyManager: proxies.eigenStrategyManager, + tokenStakingNodesManager: proxies.tokenStakingNodesManager, + tokenStakingNodeImplementation: proxies.tokenStakingNode, + ynEigenDepositAdapterInstance: proxies.ynEigenDepositAdapterInstance, + rateProvider: proxies.rateProvider, + upgradeTimelock: proxies.timelock, + viewer: proxies.viewer, + redemptionAssetsVault: proxies.redemptionAssetsVault, + withdrawalQueueManager: proxies.withdrawalQueueManager, + wrapper: proxies.lsdWrapper, proxies: DeploymentProxies({ ynEigen: proxyAddressesEmpty, assetRegistry: proxyAddressesEmpty, @@ -192,7 +196,10 @@ contract YnEigenDeployer is BaseYnEigenScript { tokenStakingNodesManager: proxyAddressesEmpty, rateProvider: proxyAddressesEmpty, ynEigenDepositAdapter: proxyAddressesEmpty, - ynEigenViewer: proxyAddressesEmpty + ynEigenViewer: proxyAddressesEmpty, + redemptionAssetsVault: proxyAddressesEmpty, + withdrawalQueueManager: proxyAddressesEmpty, + wrapper: proxyAddressesEmpty }) }); diff --git a/script/ynEigen/YnEigenFactory.sol b/script/ynEigen/YnEigenFactory.sol index e8c759826..75566da1b 100644 --- a/script/ynEigen/YnEigenFactory.sol +++ b/script/ynEigen/YnEigenFactory.sol @@ -7,7 +7,7 @@ import {IDelegationManager} from "lib/eigenlayer-contracts/src/contracts/interfa import {IStrategyManager} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; - +import {IRedeemableAsset} from "src/interfaces/IRedeemableAsset.sol"; import {IynEigen} from "src/interfaces/IynEigen.sol"; import {IRateProvider} from "src/interfaces/IRateProvider.sol"; import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; @@ -21,7 +21,10 @@ import {TokenStakingNode} from "src/ynEIGEN/TokenStakingNode.sol"; import {AssetRegistry} from "src/ynEIGEN/AssetRegistry.sol"; import {ynEigenDepositAdapter} from "src/ynEIGEN/ynEigenDepositAdapter.sol"; import {ynEigenViewer} from "src/ynEIGEN/ynEigenViewer.sol"; -import {YnEigenInit} from "./YnEigenStructs.sol"; +import {YnEigenInit, YnEigenProxies} from "./YnEigenStructs.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; import {IwstETH} from "src/external/lido/IwstETH.sol"; import {IERC4626} from "lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; @@ -47,56 +50,44 @@ contract YnEigenFactory is IYnEigenFactory { proxy = address(new TransparentUpgradeableProxy(implementation, controller, "")); } - function deploy(YnEigenInit calldata init) - external - returns ( - ynEigen ynToken, - EigenStrategyManager eigenStrategyManager, - TokenStakingNodesManager tokenStakingNodesManager, - TokenStakingNode tokenStakingNode, - AssetRegistry assetRegistry, - ynEigenDepositAdapter ynEigenDepositAdapterInstance, - IRateProvider rateProvider, - TimelockController timelock, - ynEigenViewer viewer - ) - { + function deploy(YnEigenInit calldata init) external returns (YnEigenProxies memory _proxies) { + // Deploy proxies - ynToken = ynEigen(_deployProxy(init.implementations.ynEigen, init.timelock)); - eigenStrategyManager = - EigenStrategyManager(_deployProxy(init.implementations.eigenStrategyManager, init.timelock)); - tokenStakingNodesManager = - TokenStakingNodesManager(_deployProxy(init.implementations.tokenStakingNodesManager, init.timelock)); - tokenStakingNode = TokenStakingNode(init.implementations.tokenStakingNode); - assetRegistry = AssetRegistry(_deployProxy(init.implementations.assetRegistry, init.timelock)); - ynEigenDepositAdapterInstance = - ynEigenDepositAdapter(_deployProxy(init.implementations.depositAdapter, init.timelock)); - rateProvider = IRateProvider(_deployProxy(init.implementations.rateProvider, init.timelock)); - timelock = TimelockController(payable(init.timelock)); + _proxies.ynToken = ynEigen(_deployProxy(init.implementations.ynEigen, init.timelock)); + _proxies.eigenStrategyManager = EigenStrategyManager(_deployProxy(init.implementations.eigenStrategyManager, init.timelock)); + _proxies.tokenStakingNodesManager = TokenStakingNodesManager(_deployProxy(init.implementations.tokenStakingNodesManager, init.timelock)); + _proxies.tokenStakingNode = TokenStakingNode(init.implementations.tokenStakingNode); + _proxies.assetRegistry = AssetRegistry(_deployProxy(init.implementations.assetRegistry, init.timelock)); + _proxies.ynEigenDepositAdapterInstance = ynEigenDepositAdapter(_deployProxy(init.implementations.depositAdapter, init.timelock)); + _proxies.rateProvider = IRateProvider(_deployProxy(init.implementations.rateProvider, init.timelock)); + _proxies.redemptionAssetsVault = RedemptionAssetsVault(_deployProxy(init.implementations.redemptionAssetsVault, init.timelock)); + _proxies.withdrawalQueueManager = WithdrawalQueueManager(_deployProxy(init.implementations.withdrawalQueueManager, init.timelock)); + _proxies.lsdWrapper = LSDWrapper(_deployProxy(init.implementations.lsdWrapper, init.timelock)); + _proxies.timelock = TimelockController(payable(init.timelock)); // Initialize ynToken - ynToken.initialize( + _proxies.ynToken.initialize( ynEigen.Init({ name: init.name, symbol: init.symbol, admin: init.actors.ADMIN, pauser: init.actors.PAUSE_ADMIN, unpauser: init.actors.UNPAUSE_ADMIN, - yieldNestStrategyManager: address(eigenStrategyManager), - assetRegistry: IAssetRegistry(address(assetRegistry)), + yieldNestStrategyManager: address(_proxies.eigenStrategyManager), + assetRegistry: IAssetRegistry(address(_proxies.assetRegistry)), pauseWhitelist: new address[](0) }) ); // Initialize eigenStrategyManager - eigenStrategyManager.initialize( + _proxies.eigenStrategyManager.initialize( EigenStrategyManager.Init({ assets: init.assets, strategies: init.strategies, - ynEigen: IynEigen(address(ynToken)), + ynEigen: IynEigen(address(_proxies.ynToken)), strategyManager: IStrategyManager(init.chainAddresses.STRATEGY_MANAGER), delegationManager: IDelegationManager(init.chainAddresses.DELEGATION_MANAGER), - tokenStakingNodesManager: ITokenStakingNodesManager(address(tokenStakingNodesManager)), + tokenStakingNodesManager: ITokenStakingNodesManager(address(_proxies.tokenStakingNodesManager)), admin: init.actors.ADMIN, pauser: init.actors.PAUSE_ADMIN, unpauser: init.actors.UNPAUSE_ADMIN, @@ -108,12 +99,12 @@ contract YnEigenFactory is IYnEigenFactory { ); // Initialize assetRegistry - assetRegistry.initialize( + _proxies.assetRegistry.initialize( AssetRegistry.Init({ assets: init.assets, - rateProvider: IRateProvider(address(rateProvider)), - yieldNestStrategyManager: IYieldNestStrategyManager(address(eigenStrategyManager)), - ynEigen: IynEigen(address(ynToken)), + rateProvider: IRateProvider(address(_proxies.rateProvider)), + yieldNestStrategyManager: IYieldNestStrategyManager(address(_proxies.eigenStrategyManager)), + ynEigen: IynEigen(address(_proxies.ynToken)), admin: init.actors.ADMIN, pauser: init.actors.PAUSE_ADMIN, unpauser: init.actors.UNPAUSE_ADMIN, @@ -122,13 +113,13 @@ contract YnEigenFactory is IYnEigenFactory { ); // Initialize tokenStakingNodesManager - tokenStakingNodesManager.initialize( + _proxies.tokenStakingNodesManager.initialize( TokenStakingNodesManager.Init({ admin: address(this), // Placeholder; changed post tokenStakingNode registration stakingAdmin: address(this), // Placeholder; changed post tokenStakingNode registration strategyManager: IStrategyManager(init.chainAddresses.STRATEGY_MANAGER), delegationManager: IDelegationManager(init.chainAddresses.DELEGATION_MANAGER), - yieldNestStrategyManager: address(eigenStrategyManager), + yieldNestStrategyManager: address(_proxies.eigenStrategyManager), maxNodeCount: init.maxNodeCount, pauser: init.actors.PAUSE_ADMIN, unpauser: init.actors.UNPAUSE_ADMIN, @@ -138,19 +129,53 @@ contract YnEigenFactory is IYnEigenFactory { }) ); + // initialize eigenStrategyManager + { + _proxies.eigenStrategyManager.initializeV2(address(_proxies.redemptionAssetsVault), address(_proxies.lsdWrapper), init.actors.ADMIN); + } + + // initialize RedemptionAssetsVault + { + RedemptionAssetsVault.Init memory _init = RedemptionAssetsVault.Init({ + admin: init.actors.ADMIN, + redeemer: address(_proxies.withdrawalQueueManager), + ynEigen: _proxies.ynToken, + assetRegistry: _proxies.assetRegistry + }); + _proxies.redemptionAssetsVault.initialize(_init); + } + + // initialize WithdrawalQueueManager + { + WithdrawalQueueManager.Init memory _init = WithdrawalQueueManager.Init({ + name: "ynLSDe Withdrawal Manager", + symbol: "ynLSDeWM", + redeemableAsset: IRedeemableAsset(address(_proxies.ynToken)), + redemptionAssetsVault: _proxies.redemptionAssetsVault, + admin: init.actors.ADMIN, + withdrawalQueueAdmin: init.actors.ADMIN, + redemptionAssetWithdrawer: init.actors.ADMIN, + requestFinalizer: init.actors.ADMIN, + // withdrawalFee: 500, // 0.05% + withdrawalFee: 0, + feeReceiver: init.actors.ADMIN + }); + _proxies.withdrawalQueueManager.initialize(_init); + } + // Register tokenStakingNode - tokenStakingNodesManager.registerTokenStakingNode(address(tokenStakingNode)); + _proxies.tokenStakingNodesManager.registerTokenStakingNode(address(_proxies.tokenStakingNode)); // Set roles post tokenStakingNode registration - tokenStakingNodesManager.grantRole(tokenStakingNodesManager.DEFAULT_ADMIN_ROLE(), init.actors.ADMIN); - tokenStakingNodesManager.grantRole(tokenStakingNodesManager.STAKING_ADMIN_ROLE(), init.timelock); - tokenStakingNodesManager.revokeRole(tokenStakingNodesManager.STAKING_ADMIN_ROLE(), address(this)); - tokenStakingNodesManager.revokeRole(tokenStakingNodesManager.DEFAULT_ADMIN_ROLE(), address(this)); + _proxies.tokenStakingNodesManager.grantRole(_proxies.tokenStakingNodesManager.DEFAULT_ADMIN_ROLE(), init.actors.ADMIN); + _proxies.tokenStakingNodesManager.grantRole(_proxies.tokenStakingNodesManager.STAKING_ADMIN_ROLE(), init.timelock); + _proxies.tokenStakingNodesManager.revokeRole(_proxies.tokenStakingNodesManager.STAKING_ADMIN_ROLE(), address(this)); + _proxies.tokenStakingNodesManager.revokeRole(_proxies.tokenStakingNodesManager.DEFAULT_ADMIN_ROLE(), address(this)); // ynEigenDepositAdapter - ynEigenDepositAdapterInstance.initialize( + _proxies.ynEigenDepositAdapterInstance.initialize( ynEigenDepositAdapter.Init({ - ynEigen: address(ynToken), + ynEigen: address(_proxies.ynToken), wstETH: init.chainAddresses.WSTETH_ADDRESS, woETH: init.chainAddresses.WOETH_ADDRESS, admin: init.actors.ADMIN @@ -160,21 +185,21 @@ contract YnEigenFactory is IYnEigenFactory { // ynEigenViewer { ynEigenViewer viewerImplementation = new ynEigenViewer( - address(assetRegistry), address(ynToken), address(tokenStakingNodesManager), address(rateProvider) + address(_proxies.assetRegistry), address(_proxies.ynToken), address(_proxies.tokenStakingNodesManager), address(_proxies.rateProvider) ); - viewer = ynEigenViewer(_deployProxy(address(viewerImplementation), init.actors.YN_SECURITY_COUNCIL)); + _proxies.viewer = ynEigenViewer(_deployProxy(address(viewerImplementation), init.actors.YN_SECURITY_COUNCIL)); } emit YnEigenDeployed( - ynToken, - eigenStrategyManager, - tokenStakingNodesManager, - tokenStakingNode, - assetRegistry, - ynEigenDepositAdapterInstance, - rateProvider, - timelock, - viewer + _proxies.ynToken, + _proxies.eigenStrategyManager, + _proxies.tokenStakingNodesManager, + _proxies.tokenStakingNode, + _proxies.assetRegistry, + _proxies.ynEigenDepositAdapterInstance, + _proxies.rateProvider, + _proxies.timelock, + _proxies.viewer ); } } diff --git a/script/ynEigen/YnEigenScript.s.sol b/script/ynEigen/YnEigenScript.s.sol index f8ee44338..e6d0d7555 100644 --- a/script/ynEigen/YnEigenScript.s.sol +++ b/script/ynEigen/YnEigenScript.s.sol @@ -7,6 +7,8 @@ import {console} from "lib/forge-std/src/console.sol"; contract YnEigenScript is YnEigenDeployer, YnEigenVerifier { function run(string memory _filePath) public { + // function run(string memory _filePath) public { + // string memory _filePath = "script/ynEigen/input/lsd-holesky.json"; _initDeployer(); _loadJson(_filePath); _validateNetwork(); diff --git a/script/ynEigen/YnEigenStructs.sol b/script/ynEigen/YnEigenStructs.sol index b6924338f..8cf4802d5 100644 --- a/script/ynEigen/YnEigenStructs.sol +++ b/script/ynEigen/YnEigenStructs.sol @@ -1,6 +1,27 @@ // SPDX-License-Identifier: BSD-3-Clause License pragma solidity ^0.8.24; +import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; +import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; +import {IRedeemableAsset} from "src/interfaces/IRedeemableAsset.sol"; +import {IynEigen} from "src/interfaces/IynEigen.sol"; +import {IRateProvider} from "src/interfaces/IRateProvider.sol"; +import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; +import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; +import {ynEigen} from "src/ynEIGEN/ynEigen.sol"; +import {TokenStakingNode} from "src/ynEIGEN/TokenStakingNode.sol"; +import {EigenStrategyManager} from "src/ynEIGEN/EigenStrategyManager.sol"; +import {AssetRegistry} from "src/ynEIGEN/AssetRegistry.sol"; +import {TokenStakingNodesManager} from "src/ynEIGEN/TokenStakingNodesManager.sol"; +import {TokenStakingNode} from "src/ynEIGEN/TokenStakingNode.sol"; +import {AssetRegistry} from "src/ynEIGEN/AssetRegistry.sol"; +import {ynEigenDepositAdapter} from "src/ynEIGEN/ynEigenDepositAdapter.sol"; +import {ynEigenViewer} from "src/ynEIGEN/ynEigenViewer.sol"; +import {YnEigenInit, YnEigenImplementations} from "./YnEigenStructs.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; + import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; @@ -32,6 +53,24 @@ struct YnEigenImplementations { address tokenStakingNode; address assetRegistry; address depositAdapter; + address redemptionAssetsVault; + address withdrawalQueueManager; + address lsdWrapper; +} + +struct YnEigenProxies { + ynEigen ynToken; + EigenStrategyManager eigenStrategyManager; + TokenStakingNodesManager tokenStakingNodesManager; + TokenStakingNode tokenStakingNode; + AssetRegistry assetRegistry; + ynEigenDepositAdapter ynEigenDepositAdapterInstance; + IRateProvider rateProvider; + TimelockController timelock; + ynEigenViewer viewer; + RedemptionAssetsVault redemptionAssetsVault; + WithdrawalQueueManager withdrawalQueueManager; + LSDWrapper lsdWrapper; } struct YnEigenInit { diff --git a/script/ynEigen/YnEigenVerifier.s.sol b/script/ynEigen/YnEigenVerifier.s.sol index 900f736ca..fcdd3a70b 100644 --- a/script/ynEigen/YnEigenVerifier.s.sol +++ b/script/ynEigen/YnEigenVerifier.s.sol @@ -155,6 +155,24 @@ contract YnEigenVerifier is BaseYnEigenScript { "ynEigenViewer", deployment.proxies.ynEigenViewer ); + + verifyProxyContract( + address(deployment.redemptionAssetsVault), + "redemptionAssetsVault", + deployment.proxies.redemptionAssetsVault + ); + + verifyProxyContract( + address(deployment.withdrawalQueueManager), + "withdrawalQueueManager", + deployment.proxies.withdrawalQueueManager + ); + + verifyProxyContract( + address(deployment.wrapper), + "wrapper", + deployment.proxies.wrapper + ); } function verifyProxyAdminOwners() internal view { @@ -248,7 +266,7 @@ contract YnEigenVerifier is BaseYnEigenScript { function verifyRoles() internal view { //-------------------------------------------------------------------------------------- - // YnEigene roles + // YnEigen roles //-------------------------------------------------------------------------------------- // DEFAULT_ADMIN_ROLE @@ -272,6 +290,13 @@ contract YnEigenVerifier is BaseYnEigenScript { ); console.log("\u2705 ynEigen: UNPAUSER_ROLE - ", vm.toString(address(actors.admin.UNPAUSE_ADMIN))); + // BURNER_ROLE + require( + deployment.ynEigen.hasRole(deployment.ynEigen.BURNER_ROLE(), address(deployment.withdrawalQueueManager)), + "ynEigen: BURNER_ROLE INVALID" + ); + console.log("\u2705 ynEigen: BURNER_ROLE - ", vm.toString(address(deployment.withdrawalQueueManager))); + //-------------------------------------------------------------------------------------- // assetRegistry roles //-------------------------------------------------------------------------------------- @@ -447,6 +472,78 @@ contract YnEigenVerifier is BaseYnEigenScript { "ynEigenDepositAdapter: DEFAULT_ADMIN_ROLE INVALID" ); console.log("\u2705 ynEigenDepositAdapter: DEFAULT_ADMIN_ROLE - ", vm.toString(address(actors.admin.ADMIN))); + + //-------------------------------------------------------------------------------------- + // redemptionAssetsVault roles + //-------------------------------------------------------------------------------------- + + // DEFAULT_ADMIN_ROLE + require( + deployment.redemptionAssetsVault.hasRole( + deployment.redemptionAssetsVault.DEFAULT_ADMIN_ROLE(), address(actors.admin.ADMIN) + ), + "redemptionAssetsVault: DEFAULT_ADMIN_ROLE INVALID" + ); + console.log("\u2705 redemptionAssetsVault: DEFAULT_ADMIN_ROLE - ", vm.toString(address(actors.admin.ADMIN))); + + // PAUSER_ROLE + require( + deployment.redemptionAssetsVault.hasRole( + deployment.redemptionAssetsVault.PAUSER_ROLE(), address(actors.admin.ADMIN) + ), + "redemptionAssetsVault: PAUSER_ROLE INVALID" + ); + console.log("\u2705 redemptionAssetsVault: PAUSER_ROLE - ", vm.toString(address(actors.admin.ADMIN))); + + // UNPAUSER_ROLE + require( + deployment.redemptionAssetsVault.hasRole( + deployment.redemptionAssetsVault.UNPAUSER_ROLE(), address(actors.admin.UNPAUSE_ADMIN) + ), + "redemptionAssetsVault: UNPAUSER_ROLE INVALID" + ); + console.log("\u2705 redemptionAssetsVault: UNPAUSER_ROLE - ", vm.toString(address(actors.admin.UNPAUSE_ADMIN))); + + //-------------------------------------------------------------------------------------- + // withdrawalQueueManager roles + //-------------------------------------------------------------------------------------- + + // DEFAULT_ADMIN_ROLE + require( + deployment.withdrawalQueueManager.hasRole( + deployment.withdrawalQueueManager.DEFAULT_ADMIN_ROLE(), address(actors.admin.ADMIN) + ), + "withdrawalQueueManager: DEFAULT_ADMIN_ROLE INVALID" + ); + console.log("\u2705 withdrawalQueueManager: DEFAULT_ADMIN_ROLE - ", vm.toString(address(actors.admin.ADMIN))); + + + // WITHDRAWAL_QUEUE_ADMIN_ROLE + require( + deployment.withdrawalQueueManager.hasRole( + deployment.withdrawalQueueManager.WITHDRAWAL_QUEUE_ADMIN_ROLE(), address(actors.admin.ADMIN) + ), + "withdrawalQueueManager: WITHDRAWAL_QUEUE_ADMIN_ROLE INVALID" + ); + console.log("\u2705 withdrawalQueueManager: WITHDRAWAL_QUEUE_ADMIN_ROLE - ", vm.toString(address(actors.admin.ADMIN))); + + // REDEMPTION_ASSET_WITHDRAWER_ROLE + require( + deployment.withdrawalQueueManager.hasRole( + deployment.withdrawalQueueManager.REDEMPTION_ASSET_WITHDRAWER_ROLE(), address(actors.ops.REDEMPTION_ASSET_WITHDRAWER) + ), + "withdrawalQueueManager: REDEMPTION_ASSET_WITHDRAWER_ROLE INVALID" + ); + console.log("\u2705 withdrawalQueueManager: REDEMPTION_ASSET_WITHDRAWER_ROLE - ", vm.toString(address(actors.ops.REDEMPTION_ASSET_WITHDRAWER))); + + // REQUEST_FINALIZER_ROLE + require( + deployment.withdrawalQueueManager.hasRole( + deployment.withdrawalQueueManager.REQUEST_FINALIZER_ROLE(), address(actors.ops.YNEIGEN_REQUEST_FINALIZER) + ), + "withdrawalQueueManager: REQUEST_FINALIZER_ROLE INVALID" + ); + console.log("\u2705 withdrawalQueueManager: REQUEST_FINALIZER_ROLE - ", vm.toString(address(actors.ops.YNEIGEN_REQUEST_FINALIZER))); } function verifySystemParameters() internal view { @@ -527,6 +624,13 @@ contract YnEigenVerifier is BaseYnEigenScript { "\u2705 ynEigenDepositAdapter: woETH - Value:", address(deployment.ynEigenDepositAdapterInstance.woETH()) ); + // EXPECTING 10 BPS + require( + deployment.withdrawalQueueManager.withdrawalFee() == 1000, + "WithdrawalQueueManager: withdrawalFee INVALID" + ); + console.log("\u2705 WithdrawalQueueManager: withdrawalFee - Value:", deployment.withdrawalQueueManager.withdrawalFee()); + console.log("\u2705 All system parameters verified successfully"); } @@ -535,6 +639,8 @@ contract YnEigenVerifier is BaseYnEigenScript { verifyTokenStakingNodesManagerDependencies(); verifyAssetRegistryDependencies(); verifyEigenStrategyManagerDependencies(); + verifyWithdrawalQueueManagerDependencies(); + verifyRedemptionAssetsVaultDependencies(); console.log("\u2705 All contract dependencies verified successfully"); } @@ -642,20 +748,59 @@ contract YnEigenVerifier is BaseYnEigenScript { ); require( - address(deployment.eigenStrategyManager.wstETH()) == address(chainAddresses.lsd.WSTETH_ADDRESS), - "eigenStrategyManager: wstETH INVALID" + address(deployment.eigenStrategyManager.wrapper()) == address(deployment.wrapper), + "eigenStrategyManager: wrapper INVALID" ); - console.log("\u2705 eigenStrategyManager: wstETH - Value:", address(deployment.eigenStrategyManager.wstETH())); + console.log("\u2705 eigenStrategyManager: wrapper - Value:", address(deployment.eigenStrategyManager.wrapper())); + } + function verifyWithdrawalQueueManagerDependencies() internal view { require( - address(deployment.eigenStrategyManager.woETH()) == address(chainAddresses.lsd.WOETH_ADDRESS), - "eigenStrategyManager: woETH INVALID" + address(deployment.withdrawalQueueManager.redeemableAsset()) == address(deployment.ynEigen), + "withdrawalQueueManager: ynEigen INVALID" ); - console.log("\u2705 eigenStrategyManager: woETH - Value:", address(deployment.eigenStrategyManager.woETH())); + console.log("\u2705 withdrawalQueueManager: ynEigen - Value:", address(deployment.withdrawalQueueManager.redeemableAsset())); + + require( + address(deployment.withdrawalQueueManager.redemptionAssetsVault()) == address(deployment.redemptionAssetsVault), + "withdrawalQueueManager: redemptionAssetsVault INVALID" + ); + console.log("\u2705 withdrawalQueueManager: redemptionAssetsVault - Value:", address(deployment.withdrawalQueueManager.redemptionAssetsVault())); + } + + function verifyRedemptionAssetsVaultDependencies() internal view { + require( + address(deployment.redemptionAssetsVault.ynEigen()) == address(deployment.ynEigen), + "redemptionAssetsVault: ynEigen INVALID" + ); + console.log("\u2705 redemptionAssetsVault: ynEigen - Value:", address(deployment.redemptionAssetsVault.ynEigen())); + + require( + address(deployment.redemptionAssetsVault.assetRegistry()) == address(deployment.assetRegistry), + "redemptionAssetsVault: assetRegistry INVALID" + ); + console.log("\u2705 redemptionAssetsVault: assetRegistry - Value:", address(deployment.redemptionAssetsVault.assetRegistry())); + + require( + address(deployment.redemptionAssetsVault.redeemer()) == address(deployment.withdrawalQueueManager), + "redemptionAssetsVault: redeemer INVALID" + ); + console.log("\u2705 redemptionAssetsVault: redeemer - Value:", address(deployment.redemptionAssetsVault.redeemer())); } function ynEigenSanityCheck() internal { - require(deployment.assetRegistry.totalAssets() >= 0, "assetRegistry: totalAssets INVALID"); - console.log("\u2705 assetRegistry: totalAssets - Value:", deployment.assetRegistry.totalAssets()); + + // Check that totalSupply is less than totalAssets + uint256 totalSupply = deployment.ynEigen.totalSupply(); + uint256 totalAssets = deployment.ynEigen.totalAssets(); + require(totalSupply <= totalAssets, "totalSupply should be less than or equal to totalAssets"); + console.log("\u2705 totalSupply is less than totalAssets"); + + // Print totalSupply and totalAssets + console.log(string.concat("Total Supply: ", vm.toString(totalSupply), " ynEigen (", vm.toString(totalSupply / 1e18), " units)")); + console.log(string.concat("Total Assets: ", vm.toString(totalAssets), " wei (", vm.toString(totalAssets / 1e18), " Unit of Account)")); + + uint256 previewRedeemResult = deployment.ynEigen.previewRedeem(1 ether); + console.log(string.concat("previewRedeem of 1 ynEigen: ", vm.toString(previewRedeemResult), " wei (", vm.toString(previewRedeemResult / 1e18), " Unit of Account)")); } } diff --git a/script/ynEigen/YnUpgrader.s.sol b/script/ynEigen/YnUpgrader.s.sol new file mode 100644 index 000000000..9ebf0ffcd --- /dev/null +++ b/script/ynEigen/YnUpgrader.s.sol @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; +import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; +import {IRedeemableAsset} from "src/interfaces/IRedeemableAsset.sol"; +import {IRedemptionAssetsVault} from "src/interfaces/IRedemptionAssetsVault.sol"; +import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; +import {IynEigen} from "src/interfaces/IynEigen.sol"; +import {ynEigen} from "src/ynEIGEN/ynEigen.sol"; +import {ynEigenDepositAdapter} from "src/ynEIGEN/ynEigenDepositAdapter.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; + + +import "forge-std/console.sol"; + +import "./BaseYnEigenScript.s.sol"; + +// ---- Usage ---- + +// deploy: +// forge script script/ynEigen/YnUpgrader.s.sol:YnUpgrader --verify --slow --legacy --etherscan-api-key $KEY --rpc-url $RPC_URL --broadcast + +// verify: +// --constructor-args $(cast abi-encode "constructor(address)" 0x5C1E6bA712e9FC3399Ee7d5824B6Ec68A0363C02) +// forge verify-contract --etherscan-api-key $KEY --watch --chain-id $CHAIN_ID --compiler-version $FULL_COMPILER_VER --verifier-url $VERIFIER_URL $ADDRESS $PATH:$FILE_NAME + +contract YnUpgrader is BaseYnEigenScript { + + // // holesky + // address yneigenProxy = 0x071bdC8eDcdD66730f45a3D3A6F794FAA37C75ED; + // address assetRegistryProxy = 0xaD31546AdbfE1EcD7137310508f112039a35b6F7; + // address ynEigenDepositAdapterProxy = 0x7d0c1F604571a1c015684e6c15f2DdEc432C5e74; + // address eigenStrategyManagerProxy = 0xA0a11A9b84bf87c0323bc183715a22eC7881B7FC; + // address tokenStakingNodesManagerProxy = 0x5c20D1a85C7d9acB503135a498E26Eb55d806552; + // TimelockController timelockController = TimelockController(payable(address(0x62173555C27C67644C5634e114e42A63A59CD7A5))); + // // + + // mainnet + address yneigenProxy = 0x35Ec69A77B79c255e5d47D5A3BdbEFEfE342630c; + address assetRegistryProxy = 0x323C933df2523D5b0C756210446eeE0fB84270fd; + address ynEigenDepositAdapterProxy = 0x9e72155d301a6555dc565315be72D295c76753c0; + address eigenStrategyManagerProxy = 0x92D904019A92B0Cafce3492Abb95577C285A68fC; + address tokenStakingNodesManagerProxy = 0x6B566CB6cDdf7d140C59F84594756a151030a0C3; + TimelockController timelockController = TimelockController(payable(address(0xbB73f8a5B0074b27c6df026c77fA08B0111D017A))); + + TransparentUpgradeableProxy redemptionAssetsVaultProxy; + TransparentUpgradeableProxy withdrawalQueueManagerProxy; + TransparentUpgradeableProxy wrapperProxy; + + function run() public { + + + // Assert proxy admins for existing poxies + assertProxyAdminOwnedByTimelock(yneigenProxy); + assertProxyAdminOwnedByTimelock(assetRegistryProxy); + assertProxyAdminOwnedByTimelock(ynEigenDepositAdapterProxy); + assertProxyAdminOwnedByTimelock(eigenStrategyManagerProxy); + assertProxyAdminOwnedByTimelock(tokenStakingNodesManagerProxy); + + vm.startBroadcast(vm.envUint("DEPLOYER_PRIVATE_KEY")); + + // deploy RedemptionAssetsVault + address _redemptionAssetsVaultImpl; + { + _redemptionAssetsVaultImpl = address(new RedemptionAssetsVault()); + redemptionAssetsVaultProxy = new TransparentUpgradeableProxy( + _redemptionAssetsVaultImpl, + address(timelockController), + "" + ); + } + + // deploy WithdrawalQueueManager + address _withdrawalQueueManagerImpl; + { + _withdrawalQueueManagerImpl = address(new WithdrawalQueueManager()); + withdrawalQueueManagerProxy = new TransparentUpgradeableProxy( + _withdrawalQueueManagerImpl, + address(timelockController), + "" + ); + } + + // deploy wrapper + address _wrapperImpl; + { + _wrapperImpl = address(new LSDWrapper( + chainAddresses.lsd.WSTETH_ADDRESS, + chainAddresses.lsd.WOETH_ADDRESS, + chainAddresses.lsd.OETH_ADDRESS, + chainAddresses.lsd.STETH_ADDRESS + )); + wrapperProxy = new TransparentUpgradeableProxy( + _wrapperImpl, + address(timelockController), + abi.encodeWithSignature("initialize()") + ); + } + + // Assert proxy admins for new proxies + assertProxyAdminOwnedByTimelock(address(redemptionAssetsVaultProxy)); + assertProxyAdminOwnedByTimelock(address(withdrawalQueueManagerProxy)); + assertProxyAdminOwnedByTimelock(address(wrapperProxy)); + + // initialize RedemptionAssetsVault + { + RedemptionAssetsVault.Init memory _init = RedemptionAssetsVault.Init({ + admin: actors.admin.PROXY_ADMIN_OWNER, + redeemer: address(withdrawalQueueManagerProxy), + ynEigen: IynEigen(address(yneigenProxy)), + assetRegistry: IAssetRegistry(assetRegistryProxy) + }); + RedemptionAssetsVault(address(redemptionAssetsVaultProxy)).initialize(_init); + } + + // initialize WithdrawalQueueManager + { + WithdrawalQueueManager.Init memory _init = WithdrawalQueueManager.Init({ + name: "ynLSDe Withdrawal Manager", + symbol: "ynLSDeWM", + redeemableAsset: IRedeemableAsset(yneigenProxy), + redemptionAssetsVault: IRedemptionAssetsVault(address(redemptionAssetsVaultProxy)), + admin: actors.admin.PROXY_ADMIN_OWNER, + withdrawalQueueAdmin: actors.admin.ADMIN, + redemptionAssetWithdrawer: actors.ops.REDEMPTION_ASSET_WITHDRAWER, + requestFinalizer: actors.ops.YNEIGEN_REQUEST_FINALIZER, + withdrawalFee: 1000, + feeReceiver: actors.admin.FEE_RECEIVER + }); + WithdrawalQueueManager(address(withdrawalQueueManagerProxy)).initialize(_init); + } + + address _ynEigenImpl = address(new ynEigen()); + address _assetRegistryImpl = address(new AssetRegistry()); + address _tokenStakingNodesManagerImpl = address(new TokenStakingNodesManager()); + address _ynEigenDepositAdapterImpl = address(new ynEigenDepositAdapter()); + address _eigenStrategyManagerImpl = address(new EigenStrategyManager()); + address _tokenStakingNodeImpl = address(new TokenStakingNode()); + + { + _upgradeContracts( + _ynEigenImpl, + _assetRegistryImpl, + _tokenStakingNodesManagerImpl, + _ynEigenDepositAdapterImpl, + _eigenStrategyManagerImpl, + _tokenStakingNodeImpl + ); + } + + vm.stopBroadcast(); + + console.log("====================================="); + console.log("====================================="); + console.log("_redemptionAssetsVaultProxy: ", address(redemptionAssetsVaultProxy)); + console.log("_redemptionAssetsVaultImpl: ", address(_redemptionAssetsVaultImpl)); + console.log("_withdrawalQueueManagerProxy: ", address(withdrawalQueueManagerProxy)); + console.log("_withdrawalQueueManagerImpl: ", address(_withdrawalQueueManagerImpl)); + console.log("_wrapperProxy: ", address(wrapperProxy)); + console.log("_wrapperImpl: ", address(_wrapperImpl)); + console.log("_ynEigenImpl: ", _ynEigenImpl); + console.log("_assetRegistryImpl: ", _assetRegistryImpl); + console.log("_tokenStakingNodesManagerImpl: ", _tokenStakingNodesManagerImpl); + console.log("_eigenStrategyManagerImpl: ", _eigenStrategyManagerImpl); + console.log("_ynEigenDepositAdapterImpl: ", _ynEigenDepositAdapterImpl); + // _printBurnerRole(); + console.log("====================================="); + console.log("====================================="); + } + + function _upgradeContracts( + address _ynEigenImpl, + address _assetRegistryImpl, + address _tokenStakingNodesManagerImpl, + address _ynEigenDepositAdapterImpl, + address _eigenStrategyManagerImpl, + address _tokenStakingNodeImpl + ) internal { + + address[] memory _proxyAddresses = new address[](3); + _proxyAddresses[0] = address(yneigenProxy); + _proxyAddresses[1] = address(assetRegistryProxy); + _proxyAddresses[2] = address(tokenStakingNodesManagerProxy); + address[] memory _newImplementations = new address[](3); + _newImplementations[0] = _ynEigenImpl; + _newImplementations[1] = _assetRegistryImpl; + _newImplementations[2] = _tokenStakingNodesManagerImpl; + + address[] memory targets = new address[](6); + uint256[] memory values = new uint256[](6); + bytes[] memory payloads = new bytes[](6); + bytes32 predecessor = bytes32(0); + bytes32 salt = bytes32(0); + uint256 delay = timelockController.getMinDelay(); + + for (uint256 i = 0; i < _proxyAddresses.length; i++) { + bytes memory _data = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + _proxyAddresses[i], // proxy + _newImplementations[i], // implementation + "" + ); + targets[i] = getTransparentUpgradeableProxyAdminAddress(_proxyAddresses[i]); + values[i] = 0; + payloads[i] = _data; + } + + targets[3] = address(tokenStakingNodesManagerProxy); + values[3] = 0; + payloads[3] = abi.encodeWithSignature( + "upgradeTokenStakingNode(address)", + _tokenStakingNodeImpl + ); + + targets[4] = getTransparentUpgradeableProxyAdminAddress(address(eigenStrategyManagerProxy)); + values[4] = 0; + payloads[4] = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + address(eigenStrategyManagerProxy), // proxy + _eigenStrategyManagerImpl, // implementation + abi.encodeWithSignature( + "initializeV2(address,address,address)", + address(redemptionAssetsVaultProxy), + address(wrapperProxy), + actors.ops.YNEIGEN_WITHDRAWAL_MANAGER + ) + ); + + targets[5] = getTransparentUpgradeableProxyAdminAddress(address(ynEigenDepositAdapterProxy)); + values[5] = 0; + payloads[5] = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + ynEigenDepositAdapterProxy, // proxy + _ynEigenDepositAdapterImpl, // implementation + abi.encodeWithSignature("initializeV2(address)", address(wrapperProxy)) + ); + + // vm.prank(actors.wallets.YNSecurityCouncil); + // timelockController.scheduleBatch(targets, values, payloads, predecessor, salt, delay); + + // print all targets, values, payloads + for (uint256 i = 0; i < targets.length; i++) { + console.log("====================================="); + console.log("i: ", i); + console.log("targets: ", targets[i]); + console.log("values: ", values[i]); + console.log("payloads:"); + console.logBytes(payloads[i]); + } + console.log("predecessor:"); + console.logBytes32(predecessor); + console.log("salt:"); + console.logBytes32(salt); + console.log("delay: ", delay); + console.log("====================================="); + + // skip(delay); + + // vm.prank(actors.wallets.YNSecurityCouncil); + // timelockController.executeBatch(targets, values, payloads, predecessor, salt); + } + + + function assertProxyAdminOwnedByTimelock(address proxyAddress) internal view { + address proxyAdminOwner = ProxyAdmin(getTransparentUpgradeableProxyAdminAddress(proxyAddress)).owner(); + require(proxyAdminOwner == address(timelockController), "Proxy admin not owned by timelock"); + } + + function _printBurnerRole() private view { + console.log("====================================="); + console.log("ynEigen(yneigen).BURNER_ROLE(): "); + console.logBytes32(ynEigen(yneigenProxy).BURNER_ROLE()); + console.log("====================================="); + } + + +// MAINNET + +// == Logs == +// ===================================== +// i: 0 +// targets: 0x1bfF798A6072597c401f7C83A6a1096Ae5F0aFf7 +// values: 0 +// payloads: +// 0x9623609d00000000000000000000000035ec69a77b79c255e5d47d5a3bdbefefe342630c000000000000000000000000989c5e2509c501deb6195b9f525d9092514041b400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 1 +// targets: 0xDf92BE359fB53846cCdaC8FFF1884314533949C7 +// values: 0 +// payloads: +// 0x9623609d000000000000000000000000323c933df2523d5b0c756210446eee0fb84270fd00000000000000000000000094db8f0d5bbccebf6d8288d06eb53bb80ca125bd00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 2 +// targets: 0x850d012115fb4D90711F53e86B2945019Bf7F36C +// values: 0 +// payloads: +// 0x9623609d0000000000000000000000006b566cb6cddf7d140c59f84594756a151030a0c300000000000000000000000081f34d0db58a7934549d9b2b1e76542ed9801b1f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 3 +// targets: 0x6B566CB6cDdf7d140C59F84594756a151030a0C3 +// values: 0 +// payloads: +// 0xa39cebe9000000000000000000000000c602682b9ebc9719181b7a2b2479291cba26f801 +// ===================================== +// i: 4 +// targets: 0x69C34FB00Ebc0d7ac09Ab7968D2Eb9a07C2eB301 +// values: 0 +// payloads: +// 0x9623609d00000000000000000000000092d904019a92b0cafce3492abb95577c285a68fc0000000000000000000000001776dea5799fc7ad10b6039f6e1927fefd731e85000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000642c3bb44a00000000000000000000000073bc33999c34a5126ca19dc900f22690c288d55e00000000000000000000000099db7619c018d61dbc2822767b63240d311d699200000000000000000000000015519e68ca7544d1c919a2a6e9065375a1f0c80a00000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 5 +// targets: 0x7D779806B0c6A0201984b82e57830B84a75c3C07 +// values: 0 +// payloads: +// 0x9623609d0000000000000000000000009e72155d301a6555dc565315be72d295c76753c00000000000000000000000008ef7a066bf2cf76bad826c1de8d314badf057b520000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002429b6eca900000000000000000000000099db7619c018d61dbc2822767b63240d311d699200000000000000000000000000000000000000000000000000000000 +// predecessor: +// 0x0000000000000000000000000000000000000000000000000000000000000000 +// salt: +// 0x0000000000000000000000000000000000000000000000000000000000000000 +// delay: 259200 +// ===================================== +// ===================================== +// ===================================== +// _redemptionAssetsVaultProxy: 0x73bC33999C34a5126CA19dC900F22690C288D55e +// _redemptionAssetsVaultImpl: 0x9892A40FE6e17d4C88a92b2e37c12981bAA6F14A +// _withdrawalQueueManagerProxy: 0x8Face3283E20b19d98a7a132274B69C1304D60b4 +// _withdrawalQueueManagerImpl: 0xaac93A4ddE34CE9ad9dD8556B9faDd83380a5D64 +// _wrapperProxy: 0x99dB7619C018D61dBC2822767B63240d311d6992 +// _wrapperImpl: 0x7C31a924B01a20642aF2460d7Fe24A2FEf89074d +// _ynEigenImpl: 0x989C5E2509C501deB6195b9f525d9092514041b4 +// _assetRegistryImpl: 0x94db8f0d5bBCCEBF6d8288d06eb53bB80cA125bd +// _tokenStakingNodesManagerImpl: 0x81f34d0DB58A7934549D9B2B1E76542ED9801B1f +// _eigenStrategyManagerImpl: 0x1776deA5799fc7ad10b6039f6E1927fEfd731E85 +// _ynEigenDepositAdapterImpl: 0x8Ef7a066bf2Cf76baD826C1De8D314badF057b52 +// _tokenStakingNodeImpl: 0xc602682b9ebc9719181b7a2b2479291cba26f801 + +// address redemptionAssetsVaultProxyAdmin = 0xE5E91680FE69F508B92bdCBCA2f867baAF58BAbB; +// address withdrawalQueueManagerProxyAdmin = 0xe612764D1986693f46e99605d274Bbe28c3F03a7; +// address wrapperProxyAdmin = 0x151057A14a4c84403e77C1fbc4f22a8156f63A4B; + +// ===================================== +// ===================================== + +// HOLESKY + +// targets -- [0x31456Eef519b7ab236e3638297Ed392390bf304F,0x4248392db8Ee31aA579822207d059A28A38c4510,0x18ED5129bCEfA996B4cade4e614c8941De3126d2,0x5c20D1a85C7d9acB503135a498E26Eb55d806552,0x010c60d663fddDAA076F0cE63f6692f0b5605fE5,0x9E9ce6D0fD72c7A31Eb7D99d8eCEA4b35a4FD088] +// values -- [0,0,0,0,0,0] +// payloads -- [0x9623609d000000000000000000000000071bdc8edcdd66730f45a3d3a6f794faa37c75ed000000000000000000000000350793a4b8f19ae1a67e5b4f3646483847cb755000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000,0x9623609d000000000000000000000000ad31546adbfe1ecd7137310508f112039a35b6f7000000000000000000000000b8d77186574bb4951c20464dbbfb31c6b018c4b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000,0x9623609d0000000000000000000000005c20d1a85c7d9acb503135a498e26eb55d8065520000000000000000000000003e07b130533a8d3285203c697d6ff2b25996397b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000,0xa39cebe90000000000000000000000004486c96883ee436525e11cfb1b0f589c11ff75c6,0x9623609d000000000000000000000000a0a11a9b84bf87c0323bc183715a22ec7881b7fc0000000000000000000000000b02f50fb5c498eb63231f65844b88763b91c5c9000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000642c3bb44a000000000000000000000000d536087701fff805d20ee6651e55c90d645fd1a30000000000000000000000008f61bcb28c5b88e5f10ec5bb3c18f231d763a3090000000000000000000000000e36e2bcd71059e02822dfe52cba900730b07c0700000000000000000000000000000000000000000000000000000000,0x9623609d0000000000000000000000007d0c1f604571a1c015684e6c15f2ddec432c5e740000000000000000000000009e12251f0a7728d6804aba297a7ce725c4b77e4c0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002429b6eca90000000000000000000000008f61bcb28c5b88e5f10ec5bb3c18f231d763a30900000000000000000000000000000000000000000000000000000000] +// ===================================== +// i: 0 +// targets: 0x31456Eef519b7ab236e3638297Ed392390bf304F +// values: 0 +// payloads: +// 0x9623609d000000000000000000000000071bdc8edcdd66730f45a3d3a6f794faa37c75ed000000000000000000000000350793a4b8f19ae1a67e5b4f3646483847cb755000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 1 +// targets: 0x4248392db8Ee31aA579822207d059A28A38c4510 +// values: 0 +// payloads: +// 0x9623609d000000000000000000000000ad31546adbfe1ecd7137310508f112039a35b6f7000000000000000000000000b8d77186574bb4951c20464dbbfb31c6b018c4b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 2 +// targets: 0x18ED5129bCEfA996B4cade4e614c8941De3126d2 +// values: 0 +// payloads: +// 0x9623609d0000000000000000000000005c20d1a85c7d9acb503135a498e26eb55d8065520000000000000000000000003e07b130533a8d3285203c697d6ff2b25996397b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 3 +// targets: 0x5c20D1a85C7d9acB503135a498E26Eb55d806552 +// values: 0 +// payloads: +// 0xa39cebe90000000000000000000000004486c96883ee436525e11cfb1b0f589c11ff75c6 +// ===================================== +// i: 4 +// targets: 0x010c60d663fddDAA076F0cE63f6692f0b5605fE5 +// values: 0 +// payloads: +// 0x9623609d000000000000000000000000a0a11a9b84bf87c0323bc183715a22ec7881b7fc0000000000000000000000000b02f50fb5c498eb63231f65844b88763b91c5c9000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000642c3bb44a000000000000000000000000d536087701fff805d20ee6651e55c90d645fd1a30000000000000000000000008f61bcb28c5b88e5f10ec5bb3c18f231d763a3090000000000000000000000000e36e2bcd71059e02822dfe52cba900730b07c0700000000000000000000000000000000000000000000000000000000 +// ===================================== +// i: 5 +// targets: 0x9E9ce6D0fD72c7A31Eb7D99d8eCEA4b35a4FD088 +// values: 0 +// payloads: +// 0x9623609d0000000000000000000000007d0c1f604571a1c015684e6c15f2ddec432c5e740000000000000000000000009e12251f0a7728d6804aba297a7ce725c4b77e4c0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002429b6eca90000000000000000000000008f61bcb28c5b88e5f10ec5bb3c18f231d763a30900000000000000000000000000000000000000000000000000000000 +// predecessor: +// 0x0000000000000000000000000000000000000000000000000000000000000000 +// salt: +// 0x0000000000000000000000000000000000000000000000000000000000000000 +// delay: 900 +// ===================================== +// ===================================== +// ===================================== +// _redemptionAssetsVaultProxy: 0xd536087701fFf805d20ee6651E55C90D645fD1a3 +// _redemptionAssetsVaultImpl: 0x398e9AE08179E2e07dDD51C7DCB9d585F3abC31A +// _withdrawalQueueManagerProxy: 0xaF8052DC454318D52A4478a91aCa14305590389f +// _withdrawalQueueManagerImpl: 0xf1B38e1ef304dE9a289219DCA7350f8cEE36C509 +// _wrapperProxy: 0x8F61bcb28C5b88e5F10ec5bb3C18f231D763A309 +// _wrapperImpl: 0xAd13B029FaF660a45b6F81888bB2fd1EF235Ef30 +// _ynEigenImpl: 0x350793a4B8F19Ae1a67E5b4F3646483847CB7550 +// _assetRegistryImpl: 0xB8d77186574BB4951C20464DBBfB31C6b018c4B0 +// _tokenStakingNodesManagerImpl: 0x3E07B130533A8D3285203c697d6ff2b25996397B +// _eigenStrategyManagerImpl: 0x0B02f50fB5c498eB63231f65844B88763b91C5C9 +// _ynEigenDepositAdapterImpl: 0x9E12251f0A7728d6804Aba297a7CE725C4B77e4c +// ===================================== +// ===================================== +} \ No newline at end of file diff --git a/src/WithdrawalQueueManager.sol b/src/WithdrawalQueueManager.sol index 0a72c28f9..3d69c95e7 100644 --- a/src/WithdrawalQueueManager.sol +++ b/src/WithdrawalQueueManager.sol @@ -2,8 +2,6 @@ pragma solidity ^0.8.24; import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; -import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {IERC20Metadata} from "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IWithdrawalQueueManager} from "src/interfaces/IWithdrawalQueueManager.sol"; import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol"; diff --git a/src/WithdrawalsProcessor.sol b/src/WithdrawalsProcessor.sol index 538bc6e88..445dc6dc8 100644 --- a/src/WithdrawalsProcessor.sol +++ b/src/WithdrawalsProcessor.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.24; import {IStakingNodesManager} from "./interfaces/IStakingNodesManager.sol"; import {IDelegationManager} from "lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; -import {IStakingNodesManager, IStakingNodesManager as WithdrawalAction} from "./interfaces/IStakingNodesManager.sol"; +import {IStakingNodesManager} from "./interfaces/IStakingNodesManager.sol"; import {Initializable} from "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; diff --git a/src/interfaces/IAssetRegistry.sol b/src/interfaces/IAssetRegistry.sol index 2e759f4ba..41c879ef4 100644 --- a/src/interfaces/IAssetRegistry.sol +++ b/src/interfaces/IAssetRegistry.sol @@ -15,11 +15,13 @@ interface IAssetRegistry { AssetStatus status; } + function getAssets() external view returns (IERC20[] memory); function assetData(IERC20 asset) external view returns (AssetData memory); function addAsset(IERC20 asset) external; function disableAsset(IERC20 asset) external; function deleteAsset(IERC20 asset) external; function totalAssets() external view returns (uint256); function convertToUnitOfAccount(IERC20 asset, uint256 amount) external view returns (uint256); + function convertFromUnitOfAccount(IERC20 asset, uint256 amount) external view returns (uint256); function assetIsSupported(IERC20 asset) external view returns (bool); } diff --git a/src/interfaces/IEigenStrategyManager.sol b/src/interfaces/IEigenStrategyManager.sol index c79372011..a9912c2b7 100644 --- a/src/interfaces/IEigenStrategyManager.sol +++ b/src/interfaces/IEigenStrategyManager.sol @@ -5,7 +5,8 @@ import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStra import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IwstETH} from "src/external/lido/IwstETH.sol"; import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; - +import {IynEigen} from "src/interfaces/IynEigen.sol"; +import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; interface IEigenStrategyManager { @@ -21,4 +22,6 @@ interface IEigenStrategyManager { function woETH() external view returns (IERC4626); function oETH() external view returns (IERC20); function stETH() external view returns (IERC20); + function ynEigen() external view returns (IynEigen); + function tokenStakingNodesManager() external view returns (ITokenStakingNodesManager); } \ No newline at end of file diff --git a/src/interfaces/IRedemptionAssetsVault.sol b/src/interfaces/IRedemptionAssetsVault.sol index 343b2fb32..9a7493e69 100644 --- a/src/interfaces/IRedemptionAssetsVault.sol +++ b/src/interfaces/IRedemptionAssetsVault.sol @@ -9,6 +9,7 @@ interface IRedemptionAssetsVault { event AssetsDeposited( address indexed asset, address indexed depositor, uint256 amount); event AssetTransferred(address indexed asset, address indexed redeemer, address indexed to, uint256 amount); event AssetWithdrawn(address indexed asset, address indexed redeemer, address indexed to, uint256 amount); + event TotalAssetsTransferred(address indexed asset, address indexed from, address indexed to, uint256 amount); /// @notice Transfers redemption assets to a specified address based on redemption. /// @dev This is only for INTERNAL USE diff --git a/src/interfaces/ITokenStakingNode.sol b/src/interfaces/ITokenStakingNode.sol index 2145c4970..1b7358900 100644 --- a/src/interfaces/ITokenStakingNode.sol +++ b/src/interfaces/ITokenStakingNode.sol @@ -37,4 +37,20 @@ interface ITokenStakingNode { ) external; function undelegate() external; + + function getQueuedSharesAndWithdrawn(IStrategy _strategy, IERC20 _asset) external view returns (uint256, uint256); + function queueWithdrawals(IStrategy _strategy, uint256 _shares) external returns (bytes32[] memory _fullWithdrawalRoots); + function completeQueuedWithdrawals( + uint256 _nonce, + uint32 _startBlock, + uint256 _shares, + IStrategy _strategy, + uint256[] memory _middlewareTimesIndexes, + bool updateTokenStakingNodesBalances + ) external; + + function deallocateTokens(IERC20 _token, uint256 _amount) external; + + function queuedShares(IStrategy _strategy) external view returns (uint256); + function withdrawn(IERC20 _token) external view returns (uint256); } diff --git a/src/interfaces/ITokenStakingNodesManager.sol b/src/interfaces/ITokenStakingNodesManager.sol index e6c2797a5..5dfb5f26c 100644 --- a/src/interfaces/ITokenStakingNodesManager.sol +++ b/src/interfaces/ITokenStakingNodesManager.sol @@ -24,4 +24,6 @@ interface ITokenStakingNodesManager { function hasYieldNestStrategyManagerRole(address) external view returns (bool); function getNodeById(uint256 nodeId) external view returns (ITokenStakingNode); + + function yieldNestStrategyManager() external view returns (address); } diff --git a/src/interfaces/IWrapper.sol b/src/interfaces/IWrapper.sol new file mode 100644 index 000000000..025d5ee31 --- /dev/null +++ b/src/interfaces/IWrapper.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +interface IWrapper { + + /// @notice Wraps the given amount of the given token. + /// @param _amount The amount to wrap. + /// @param _token The token to wrap. + /// @return The amount of wrapped tokens and the wrapped token. + function wrap(uint256 _amount, IERC20 _token) external returns (uint256, IERC20); + + /// @notice Unwraps the given amount of the given token. + /// @param _amount The amount to unwrap. + /// @param _token The token to unwrap. + /// @return The amount of unwrapped tokens and the unwrapped token. + function unwrap(uint256 _amount, IERC20 _token) external returns (uint256, IERC20); + + /// @notice Converts the user's underlying asset amount to the equivalent user asset amount. + /// @dev This function handles the conversion for wrapped staked ETH (wstETH) and wrapped other ETH (woETH), + /// returning the equivalent amount in the respective wrapped token. + /// @param _asset The ERC20 token for which the conversion is being made. + /// @param _userUnderlyingView The amount of the underlying asset. + /// @return The equivalent amount in the user asset denomination. + function toUserAssetAmount(IERC20 _asset, uint256 _userUnderlyingView) external view returns (uint256); +} \ No newline at end of file diff --git a/src/interfaces/IYieldNestStrategyManager.sol b/src/interfaces/IYieldNestStrategyManager.sol index 5f2aaf448..f690a8ca0 100644 --- a/src/interfaces/IYieldNestStrategyManager.sol +++ b/src/interfaces/IYieldNestStrategyManager.sol @@ -2,9 +2,26 @@ pragma solidity ^0.8.24; import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; +import {IRedemptionAssetsVault} from "src/interfaces/IRedemptionAssetsVault.sol"; +import {IWrapper} from "src/interfaces/IWrapper.sol"; + + +interface IRedemptionAssetsVaultExt is IRedemptionAssetsVault { + function deposit(uint256 amount, address asset) external; + function balances(address asset) external view returns (uint256 amount); + function assetBalances(IERC20[] calldata assetsArray) external view returns (uint256[] memory balances); +} interface IYieldNestStrategyManager { + struct WithdrawalAction { + uint256 nodeId; + uint256 amountToReinvest; + uint256 amountToQueue; + address asset; + } + function getStakedAssetsBalances( IERC20[] calldata assets ) external view returns (uint256[] memory stakedBalances); @@ -13,4 +30,15 @@ interface IYieldNestStrategyManager { function supportsAsset(IERC20 asset) external view returns (bool); + function tokenStakingNodesManager() external view returns (ITokenStakingNodesManager); + + function processPrincipalWithdrawals(WithdrawalAction[] calldata _actions) external; + + function redemptionAssetsVault() external view returns (IRedemptionAssetsVaultExt); + + function wrapper() external view returns (IWrapper); + + function isStakingNodesWithdrawer(address _address) external view returns (bool); + + function updateTokenStakingNodesBalances(IERC20 asset) external; } \ No newline at end of file diff --git a/src/interfaces/IynEigen.sol b/src/interfaces/IynEigen.sol index 5a29131bb..d6d7737b5 100644 --- a/src/interfaces/IynEigen.sol +++ b/src/interfaces/IynEigen.sol @@ -17,11 +17,20 @@ interface IynEigen is IERC20 { function previewDeposit(IERC20 asset, uint256 amount) external view returns (uint256); + function burn(uint256 amount) external; + + function previewRedeem(IERC20 asset, uint256 shares) external view returns (uint256 assets); + function previewRedeem(uint256 shares) external view returns (uint256); + + function convertToAssets(IERC20 asset, uint256 shares) external view returns (uint256); + function retrieveAssets( IERC20[] calldata assetsToRetrieve, uint256[] calldata amounts ) external; + function processWithdrawn(uint256 _amount, address _asset) external; + function assetBalances(IERC20[] calldata assetsArray) external view returns (uint256[] memory balances); function assetBalance(IERC20 asset) external view returns (uint256 balance); diff --git a/src/ynEIGEN/AssetRegistry.sol b/src/ynEIGEN/AssetRegistry.sol index 9e5fff958..a3c10c8fc 100644 --- a/src/ynEIGEN/AssetRegistry.sol +++ b/src/ynEIGEN/AssetRegistry.sol @@ -10,7 +10,7 @@ import {IRateProvider} from "src/interfaces/IRateProvider.sol"; import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; import "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; - +import {IRedemptionAssetsVaultExt} from "src/interfaces/IYieldNestStrategyManager.sol"; interface IAssetRegistryEvents { event AssetAdded(address indexed asset); @@ -29,7 +29,6 @@ interface IAssetRegistryEvents { //---------------------------------- ERRORS ------------------------------------------ //-------------------------------------------------------------------------------------- - error UnsupportedAsset(IERC20 asset); error Paused(); error AssetNotActive(address inactiveAsset); error AssetAlreadyActive(address asset); @@ -37,7 +36,6 @@ interface IAssetRegistryEvents { error AssetBalanceNonZeroInPool(uint256 balanceInPool); error AssetBalanceNonZeroInStrategyManager(uint256 balanceInStrategyManager); error AssetNotFound(address absentAsset); - error ZeroAmount(); error ZeroAddress(); error LengthMismatch(uint256 length1, uint256 length2); error AssetAlreadyAvailable(address asset); @@ -103,29 +101,13 @@ interface IAssetRegistryEvents { _grantRole(ASSET_MANAGER_ROLE, init.assetManagerRole); strategyManager = init.yieldNestStrategyManager; - + rateProvider = init.rateProvider; + ynEigen = init.ynEigen; + uint256 assetsLength = init.assets.length; for (uint256 i = 0; i < assetsLength; i++) { - IERC20 asset = init.assets[i]; - if (address(asset) == address(0)) { - revert ZeroAddress(); - } - if (_assetData[asset].status == AssetStatus.Active) { - revert AssetAlreadyActive(address(asset)); - } - - if (!strategyManager.supportsAsset(asset)) { - revert NoStrategyDefinedForAsset(asset); - } - - assets.push(asset); - _assetData[asset] = AssetData({ - status: AssetStatus.Active - }); + _addAsset(init.assets[i]); } - - rateProvider = init.rateProvider; - ynEigen = init.ynEigen; } //-------------------------------------------------------------------------------------- @@ -142,6 +124,10 @@ interface IAssetRegistryEvents { onlyRole(ASSET_MANAGER_ROLE) notZeroAddress(address(asset)) whenNotPaused { + _addAsset(asset); + } + + function _addAsset(IERC20 asset) private { if (_assetData[asset].status != AssetStatus.Unavailable) { revert AssetAlreadyAvailable(address(asset)); } @@ -286,8 +272,15 @@ interface IAssetRegistryEvents { revert LengthMismatch(assetsCount, stakedAssetBalances.length); } + IRedemptionAssetsVaultExt redemptionAssetsVault = strategyManager.redemptionAssetsVault(); + uint256[] memory redemptionAssetBalances = new uint256[](assetsCount); + if (address(redemptionAssetsVault) != address(0)) { + redemptionAssetBalances = redemptionAssetsVault.assetBalances(assets); + } + for (uint256 i = 0; i < assetsCount; i++) { assetBalances[i] += stakedAssetBalances[i]; + assetBalances[i] += redemptionAssetBalances[i]; } } @@ -315,6 +308,14 @@ interface IAssetRegistryEvents { : assetRate * amount / 1e18; } + function convertFromUnitOfAccount(IERC20 asset, uint256 amount) public view returns (uint256) { + uint256 assetRate = rateProvider.rate(address(asset)); + uint8 assetDecimals = IERC20Metadata(address(asset)).decimals(); + return assetDecimals != 18 + ? amount * (10 ** assetDecimals) / assetRate + : amount * 1e18 / assetRate; + } + //-------------------------------------------------------------------------------------- //---------------------------------- PAUSING ----------------------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/ynEIGEN/EigenStrategyManager.sol b/src/ynEIGEN/EigenStrategyManager.sol index 86599085d..f119ff26e 100644 --- a/src/ynEIGEN/EigenStrategyManager.sol +++ b/src/ynEIGEN/EigenStrategyManager.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: BSD 3-Clause License pragma solidity ^0.8.24; +import {SafeCast} from "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; import {Initializable} from "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol"; import {IStrategyManager} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; import {IDelegationManager} from "lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; -import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; +import {IYieldNestStrategyManager, IRedemptionAssetsVaultExt} from "src/interfaces/IYieldNestStrategyManager.sol"; import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; import {ITokenStakingNode} from "src/interfaces/ITokenStakingNode.sol"; @@ -15,12 +16,19 @@ import {IynEigen} from "src/interfaces/IynEigen.sol"; import {IwstETH} from "src/external/lido/IwstETH.sol"; import {IERC4626} from "lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; - +import {IWrapper} from "src/interfaces/IWrapper.sol"; +import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; interface IEigenStrategyManagerEvents { event StrategyAdded(address indexed asset, address indexed strategy); event StakedAssetsToNode(uint256 indexed nodeId, IERC20[] assets, uint256[] amounts); event DepositedToEigenlayer(IERC20[] depositAssets, uint256[] depositAmounts, IStrategy[] strategiesForNode); + event PrincipalWithdrawalProcessed(uint256 indexed nodeId, address indexed asset, uint256 amountToReinvest, uint256 amountToQueue); + event StrategyBalanceUpdated(address indexed asset, address indexed strategy, uint256 nodeCount, uint128 stakedBalance, uint128 withdrawnBalance); +} + +interface IynEigenVars { + function assetRegistry() external view returns (IAssetRegistry); } /** @title EigenStrategyManager @@ -78,6 +86,12 @@ contract EigenStrategyManager is /// @notice Role allowed to manage strategies bytes32 public constant STRATEGY_ADMIN_ROLE = keccak256("STRATEGY_ADMIN_ROLE"); + /// @notice Role allowed to manage withdrawals + bytes32 public constant WITHDRAWAL_MANAGER_ROLE = keccak256("WITHDRAWAL_MANAGER_ROLE"); + + /// @notice Role allowed to withdraw from staking nodes + bytes32 public constant STAKING_NODES_WITHDRAWER_ROLE = keccak256("STAKING_NODES_WITHDRAWER_ROLE"); + //-------------------------------------------------------------------------------------- //---------------------------------- CONSTANTS --------------------------------------- //-------------------------------------------------------------------------------------- @@ -100,10 +114,23 @@ contract EigenStrategyManager is IERC20 public oETH; IERC20 public stETH; + IRedemptionAssetsVaultExt public redemptionAssetsVault; + IWrapper public wrapper; + + struct StrategyBalance { + uint128 stakedBalance; + uint128 withdrawnBalance; + } + mapping(IStrategy => StrategyBalance) public strategiesBalance; + //-------------------------------------------------------------------------------------- //---------------------------------- INITIALIZATION ---------------------------------- //-------------------------------------------------------------------------------------- + constructor() { + _disableInitializers(); + } + struct Init { IERC20[] assets; IStrategy[] strategies; @@ -156,8 +183,90 @@ contract EigenStrategyManager is oETH = IERC20(woETH.asset()); } + function initializeV2( + address _redemptionAssetsVault, + address _wrapper, + address _withdrawer + ) external reinitializer(2) notZeroAddress(_redemptionAssetsVault) notZeroAddress(_wrapper) { + __ReentrancyGuard_init(); + + redemptionAssetsVault = IRedemptionAssetsVaultExt(_redemptionAssetsVault); + wrapper = IWrapper(_wrapper); + + _grantRole(STAKING_NODES_WITHDRAWER_ROLE, _withdrawer); + _grantRole(WITHDRAWAL_MANAGER_ROLE, _withdrawer); + + IERC20[] memory assets = IynEigenVars(address(ynEigen)).assetRegistry().getAssets(); + uint256 assetsLength = assets.length; + for (uint256 i = 0; i < assetsLength; i++) { + _updateTokenStakingNodesBalances(assets[i], IStrategy(address(0))); + } + } + //-------------------------------------------------------------------------------------- - //---------------------------------- STRATEGY ---------------------------------------- + //------------------------------------ ACCOUNTING ---------------------------------------- + //-------------------------------------------------------------------------------------- + + /// @notice Updates the staked balances for all nodes for a specific asset's strategy. + /// @dev This function should be called after any operation that changes node balances. + /// @dev In case of slashing events, users are incentivized to call this function to adjust the exchange rate. + /// @param asset The ERC20 token for which the balances are to be updated. + function updateTokenStakingNodesBalances(IERC20 asset) public { + _updateTokenStakingNodesBalances(asset, strategies[asset]); + } + + /// @notice Updates the staked balances for all nodes for a strategies. + /// @dev Should be called atomically after any node-balance-changing operation. + /// @dev On a slashing events, users will have an incentive to call this function, to decrease the exchange rate. + /// @param asset The asset for which the balances are to be updated. + /// @param strategy The strategy for which the balances are to be updated. If not provided, we search for the strategy associated with the asset. + function _updateTokenStakingNodesBalances(IERC20 asset, IStrategy strategy) internal { + + ITokenStakingNode[] memory nodes = tokenStakingNodesManager.getAllNodes(); + uint256 nodesCount = nodes.length; + + uint256 _strategiesBalance; + uint256 _strategiesWithdrawalQueueBalance; + uint256 _strategiesWithdrawnBalance; + if (address(strategy) == address(0)) strategy = strategies[asset]; + for (uint256 i; i < nodesCount; i++ ) { + ITokenStakingNode node = nodes[i]; + + _strategiesBalance += strategy.userUnderlyingView((address(node))); + + (uint256 queuedShares, uint256 strategyWithdrawnBalance) = node.getQueuedSharesAndWithdrawn(strategy, asset); + + if (queuedShares > 0) { + _strategiesWithdrawalQueueBalance += strategy.sharesToUnderlyingView(queuedShares); + } + + _strategiesWithdrawnBalance += strategyWithdrawnBalance; + } + + StrategyBalance memory _strategyBalance = StrategyBalance({ + stakedBalance: SafeCast.toUint128(_strategiesBalance + _strategiesWithdrawalQueueBalance), + withdrawnBalance: SafeCast.toUint128(_strategiesWithdrawnBalance) + }); + + + // update only if it changed + StrategyBalance memory previousStrategyBalance = strategiesBalance[strategy]; + if (previousStrategyBalance.stakedBalance != _strategyBalance.stakedBalance || + previousStrategyBalance.withdrawnBalance != _strategyBalance.withdrawnBalance) { + strategiesBalance[strategy] = _strategyBalance; + + emit StrategyBalanceUpdated( + address(asset), + address(strategy), + nodesCount, + _strategyBalance.stakedBalance, + _strategyBalance.withdrawnBalance + ); + } + } + + //-------------------------------------------------------------------------------------- + //------------------------------------ DEPOSIT ---------------------------------------- //-------------------------------------------------------------------------------------- /** @@ -215,14 +324,18 @@ contract EigenStrategyManager is } strategiesForNode[i] = strategy; } - // Transfer assets to node + + // Transfer assets to address(this) ynEigen.retrieveAssets(assets, amounts); IERC20[] memory depositAssets = new IERC20[](assetsLength); uint256[] memory depositAmounts = new uint256[](amountsLength); + IWrapper _wrapper = wrapper; for (uint256 i = 0; i < assetsLength; i++) { - (IERC20 depositAsset, uint256 depositAmount) = toEigenLayerDeposit(assets[i], amounts[i]); + // NOTE: approving also token that will not be transferred + IERC20(assets[i]).forceApprove(address(_wrapper), amounts[i]); + (uint256 depositAmount, IERC20 depositAsset) = _wrapper.unwrap(amounts[i], assets[i]); depositAssets[i] = depositAsset; depositAmounts[i] = depositAmount; @@ -234,27 +347,48 @@ contract EigenStrategyManager is node.depositAssetsToEigenlayer(depositAssets, depositAmounts, strategiesForNode); + for (uint256 i = 0; i < assetsLength; i++) { + _updateTokenStakingNodesBalances(assets[i], IStrategy(address(0))); + } + emit DepositedToEigenlayer(depositAssets, depositAmounts, strategiesForNode); } - function toEigenLayerDeposit( - IERC20 asset, - uint256 amount - ) internal returns (IERC20 depositAsset, uint256 depositAmount) { - if (address(asset) == address(wstETH)) { - // Adjust for wstETH - depositAsset = stETH; - depositAmount = wstETH.unwrap(amount); - } else if (address(asset) == address(woETH)) { - // Adjust for woeth - depositAsset = oETH; - // calling redeem with receiver and owner as address(this) - depositAmount = woETH.redeem(amount, address(this), address(this)); - } else { - // No adjustment needed - depositAsset = asset; - depositAmount = amount; - } + //-------------------------------------------------------------------------------------- + //---------------------------------- WITHDRAWALS ------------------------------------- + //-------------------------------------------------------------------------------------- + + function processPrincipalWithdrawals( + WithdrawalAction[] calldata _actions + ) public onlyRole(WITHDRAWAL_MANAGER_ROLE) { + uint256 _len = _actions.length; + for (uint256 i = 0; i < _len; ++i) { + _processPrincipalWithdrawalForNode(_actions[i]); + } + } + + function _processPrincipalWithdrawalForNode(WithdrawalAction calldata _action) internal { + + uint256 _totalAmount = _action.amountToReinvest + _action.amountToQueue; + + ITokenStakingNode _node = tokenStakingNodesManager.getNodeById(_action.nodeId); + _node.deallocateTokens(IERC20(_action.asset), _totalAmount); + + if (_action.amountToReinvest > 0) { + IynEigen _ynEigen = ynEigen; + IERC20(_action.asset).forceApprove(address(_ynEigen), _action.amountToReinvest); + _ynEigen.processWithdrawn(_action.amountToReinvest, _action.asset); + } + + if (_action.amountToQueue > 0) { + IRedemptionAssetsVaultExt _redemptionAssetsVault = redemptionAssetsVault; + IERC20(_action.asset).forceApprove(address(_redemptionAssetsVault), _action.amountToQueue); + _redemptionAssetsVault.deposit(_action.amountToQueue, _action.asset); + } + + _updateTokenStakingNodesBalances(IERC20(_action.asset), IStrategy(address(0))); + + emit PrincipalWithdrawalProcessed(_action.nodeId, _action.asset, _action.amountToReinvest, _action.amountToQueue); } //-------------------------------------------------------------------------------------- @@ -293,42 +427,15 @@ contract EigenStrategyManager is stakedBalances = new uint256[](assets.length); // Add balances contained in each TokenStakingNode, including those managed by strategies. - ITokenStakingNode[] memory nodes = tokenStakingNodesManager.getAllNodes(); - uint256 nodesCount = nodes.length; uint256 assetsCount = assets.length; for (uint256 j = 0; j < assetsCount; j++) { - IERC20 asset = assets[j]; - for (uint256 i; i < nodesCount; i++ ) { - ITokenStakingNode node = nodes[i]; - - uint256 strategyBalance = toUserAssetAmount( - asset, - strategies[asset].userUnderlyingView((address(node))) - ); - stakedBalances[j] += strategyBalance; - } + IStrategy strategy = strategies[asset]; + StrategyBalance memory balance = strategiesBalance[strategy]; + stakedBalances[j] = wrapper.toUserAssetAmount(asset, balance.stakedBalance) + balance.withdrawnBalance; } - } - /** - * @notice Converts the user's underlying asset amount to the equivalent user asset amount. - * @dev This function handles the conversion for wrapped staked ETH (wstETH) and wrapped other ETH (woETH), - * returning the equivalent amount in the respective wrapped token. - * @param asset The ERC20 token for which the conversion is being made. - * @param userUnderlyingView The amount of the underlying asset. - * @return The equivalent amount in the user asset denomination. - */ - function toUserAssetAmount(IERC20 asset, uint256 userUnderlyingView) public view returns (uint256) { - if (address(asset) == address(wstETH)) { - // Adjust for wstETH using view method, converting stETH to wstETH - return wstETH.getWstETHByStETH(userUnderlyingView); - } - if (address(asset) == address(woETH)) { - // Adjust for woETH using view method, converting oETH to woETH - return woETH.previewDeposit(userUnderlyingView); - } - return userUnderlyingView; + return stakedBalances; } /** @@ -336,7 +443,7 @@ contract EigenStrategyManager is * @param asset The ERC20 token for which the staked balance is to be retrieved. * @return stakedBalance The total staked balance of the specified asset. */ - function getStakedAssetBalance(IERC20 asset) public view returns (uint256 stakedBalance) { + function getStakedAssetBalance(IERC20 asset) external view returns (uint256 stakedBalance) { if (address(strategies[asset]) == address(0)) { revert NoStrategyDefinedForAsset(address(asset)); } @@ -358,7 +465,7 @@ contract EigenStrategyManager is function getStakedAssetBalanceForNode( IERC20 asset, uint256 nodeId - ) public view returns (uint256 stakedBalance) { + ) external view returns (uint256 stakedBalance) { if (address(strategies[asset]) == address(0)) { revert NoStrategyDefinedForAsset(address(asset)); } @@ -372,11 +479,14 @@ contract EigenStrategyManager is ITokenStakingNode node ) internal view returns (uint256 stakedBalance) { - uint256 strategyBalance = toUserAssetAmount( + IStrategy strategy = strategies[asset]; + (uint256 queuedShares, uint256 strategyWithdrawnBalance) = node.getQueuedSharesAndWithdrawn(strategy, asset); + uint256 strategyBalance = wrapper.toUserAssetAmount( asset, - strategies[asset].userUnderlyingView((address(node))) + strategy.userUnderlyingView((address(node))) + strategy.sharesToUnderlyingView(queuedShares) ); - stakedBalance += strategyBalance; + + stakedBalance += strategyBalance + strategyWithdrawnBalance; } /** @@ -388,6 +498,15 @@ contract EigenStrategyManager is return address(strategies[asset]) != address(0); } + /** + * @notice Checks if the given address has the STAKING_NODES_WITHDRAWER_ROLE. + * @param _address The address to check. + * @return True if the address has the STAKING_NODES_WITHDRAWER_ROLE, false otherwise. + */ + function isStakingNodesWithdrawer(address _address) public view returns (bool) { + return hasRole(STAKING_NODES_WITHDRAWER_ROLE, _address); + } + //-------------------------------------------------------------------------------------- //---------------------------------- MODIFIERS --------------------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/ynEIGEN/LSDWrapper.sol b/src/ynEIGEN/LSDWrapper.sol new file mode 100644 index 000000000..11764ba65 --- /dev/null +++ b/src/ynEIGEN/LSDWrapper.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {Initializable} from "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import {IERC4626} from "lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +import {IERC20, SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; + +import {IwstETH} from "src/external/lido/IwstETH.sol"; +import {IWrapper} from "src/interfaces/IWrapper.sol"; + +contract LSDWrapper is IWrapper, Initializable { + + using SafeERC20 for IERC20; + + // solhint-disable-next-line var-name-mixedcase + IERC20 public immutable wstETH; + // solhint-disable-next-line var-name-mixedcase + IERC20 public immutable woETH; + // solhint-disable-next-line var-name-mixedcase + IERC20 public immutable oETH; + // solhint-disable-next-line var-name-mixedcase + IERC20 public immutable stETH; + + // ============================================================================================ + // Constructor + // ============================================================================================ + + constructor(address _wstETH, address _woETH, address _oETH, address _stETH) { + _disableInitializers(); + + if (_wstETH == address(0) || _woETH == address(0) || _oETH == address(0) || _stETH == address(0)) { + revert ZeroAddress(); + } + + wstETH = IERC20(_wstETH); + woETH = IERC20(_woETH); + oETH = IERC20(_oETH); + stETH = IERC20(_stETH); + } + + function initialize() external initializer { + stETH.forceApprove(address(wstETH), type(uint256).max); + oETH.forceApprove(address(woETH), type(uint256).max); + } + + // ============================================================================================ + // External functions + // ============================================================================================ + + /// @inheritdoc IWrapper + function wrap(uint256 _amount, IERC20 _token) external returns (uint256, IERC20) { + if (_token == stETH) { + stETH.safeTransferFrom(msg.sender, address(this), _amount); + _amount = IwstETH(address(wstETH)).wrap(_amount); + wstETH.safeTransfer(msg.sender, _amount); + return (_amount, wstETH); + } else if (_token == oETH) { + oETH.safeTransferFrom(msg.sender, address(this), _amount); + return (IERC4626(address(woETH)).deposit(_amount, msg.sender), woETH); + } else { + return (_amount, _token); + } + } + + /// @inheritdoc IWrapper + function unwrap(uint256 _amount, IERC20 _token) external returns (uint256, IERC20) { + if (_token == wstETH) { + wstETH.safeTransferFrom(msg.sender, address(this), _amount); + _amount = IwstETH(address(wstETH)).unwrap(_amount); + stETH.safeTransfer(msg.sender, _amount); + return (_amount, stETH); + } else if (_token == woETH) { + return (IERC4626(address(woETH)).redeem(_amount, msg.sender, msg.sender), oETH); + } else { + return (_amount, _token); + } + } + + /// @inheritdoc IWrapper + function toUserAssetAmount(IERC20 _asset, uint256 _userUnderlyingView) external view returns (uint256) { + if (_asset == wstETH) { + // Adjust for wstETH using view method, converting stETH to wstETH + return IwstETH(address(wstETH)).getWstETHByStETH(_userUnderlyingView); + } + if (_asset == woETH) { + // Adjust for woETH using view method, converting oETH to woETH + return IERC4626(address(woETH)).previewDeposit(_userUnderlyingView); + } + return _userUnderlyingView; + } + + // ============================================================================================ + // Errors + // ============================================================================================ + + error ZeroAddress(); +} \ No newline at end of file diff --git a/src/ynEIGEN/RedemptionAssetsVault.sol b/src/ynEIGEN/RedemptionAssetsVault.sol new file mode 100644 index 000000000..f5aa15699 --- /dev/null +++ b/src/ynEIGEN/RedemptionAssetsVault.sol @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {Initializable} from "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; +import {ReentrancyGuardUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol"; +import {IynEigen} from "src/interfaces/IynEigen.sol"; +import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; +import {IRedemptionAssetsVault} from "src/interfaces/IRedemptionAssetsVault.sol"; +import {ETH_ASSET, YNETH_UNIT} from "src/Constants.sol"; + +contract RedemptionAssetsVault is IRedemptionAssetsVault, Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable { + + using SafeERC20 for IERC20; + + //-------------------------------------------------------------------------------------- + //---------------------------------- ERRORS ------------------------------------------ + //-------------------------------------------------------------------------------------- + + error ZeroAddress(); + error InsufficientAssetBalance(address asset, uint256 requestedAmount, uint256 balance); + error ContractPaused(); + error ContractUnpaused(); + error NotRedeemer(address caller); + error AssetNotSupported(); + event Paused(); + event Unpaused(); + + //-------------------------------------------------------------------------------------- + //---------------------------------- EVENTS ------------------------------------------ + //-------------------------------------------------------------------------------------- + + event AssetDeposited(address indexed asset, address indexed sender, uint256 amount); + + //-------------------------------------------------------------------------------------- + //---------------------------------- ROLES ------------------------------------------- + //-------------------------------------------------------------------------------------- + + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + bytes32 public constant UNPAUSER_ROLE = keccak256("UNPAUSER_ROLE"); + + //-------------------------------------------------------------------------------------- + //---------------------------------- VARIABLES --------------------------------------- + //-------------------------------------------------------------------------------------- + + IynEigen public ynEigen; + IAssetRegistry public assetRegistry; + bool public paused; + address public redeemer; + + mapping(address asset => uint256 balance) public balances; + + constructor() { + _disableInitializers(); + } + + // Initializer with Init struct and roles + struct Init { + address admin; + address redeemer; + IynEigen ynEigen; + IAssetRegistry assetRegistry; + } + + function initialize(Init memory init) + external + notZeroAddress(init.admin) + notZeroAddress(init.redeemer) + notZeroAddress(address(init.ynEigen)) + notZeroAddress(address(init.assetRegistry)) + initializer { + __AccessControl_init(); + __ReentrancyGuard_init(); + _grantRole(DEFAULT_ADMIN_ROLE, init.admin); + _grantRole(PAUSER_ROLE, init.admin); + _grantRole(UNPAUSER_ROLE, init.admin); + + redeemer = init.redeemer; + ynEigen = init.ynEigen; + assetRegistry = init.assetRegistry; + paused = false; + } + + //-------------------------------------------------------------------------------------- + //------------------------------------- VIEW ------------------------------------------ + //-------------------------------------------------------------------------------------- + + function assetBalances(IERC20[] calldata assetsArray) public view returns (uint256[] memory _balances) { + uint256 len = assetsArray.length; + _balances = new uint256[](len); + for (uint256 i = 0; i < len; ++i) { + _balances[i] = balances[address(assetsArray[i])]; + } + } + + function previewClaim(uint256 amount) external view returns (IERC20[] memory assets, uint256[] memory assetsOut) { + uint256 balance = availableRedemptionAssets(); + if (balance < amount) revert InsufficientAssetBalance(ETH_ASSET, amount, balance); + + assets = assetRegistry.getAssets(); + assetsOut = new uint256[](assets.length); + for (uint256 i = 0; i < assets.length; ++i) { + IERC20 asset = assets[i]; + uint256 assetBalance = balances[address(asset)]; + if (assetBalance > 0) { + uint256 assetBalanceInUnit = assetRegistry.convertToUnitOfAccount(asset, assetBalance); + if (assetBalanceInUnit >= amount) { + uint256 reqAmountInAsset = assetRegistry.convertFromUnitOfAccount(asset, amount); + assetsOut[i] = reqAmountInAsset; + break; + } else { + amount -= assetBalanceInUnit; + assetsOut[i] = assetBalance; + } + } + } + } + + //-------------------------------------------------------------------------------------- + //---------------------------------- REDEMPTION -------------------------------------- + //-------------------------------------------------------------------------------------- + + function deposit(uint256 amount, address asset) external { + if (!assetRegistry.assetIsSupported(IERC20(asset))) revert AssetNotSupported(); + + balances[asset] += amount; + IERC20(asset).safeTransferFrom(msg.sender, address(this), amount); + + emit AssetDeposited(asset, msg.sender, amount); + } + + /** + * @notice Calculates the current redemption rate of ynETH to ETH. + * @return The current redemption rate as a uint256. + */ + function redemptionRate() public view returns (uint256) { + return ynEigen.previewRedeem(YNETH_UNIT); + } + + /** + * @notice Returns the total amount of assets available for redemption. + * @return _availableRedemptionAssets The available unit-of-account-denominated balance as a uint256. + */ + function availableRedemptionAssets() public view returns (uint256 _availableRedemptionAssets) { + + IERC20[] memory assets = assetRegistry.getAssets(); + + uint256 len = assets.length; + for (uint256 i = 0; i < len; ++i) { + IERC20 asset = assets[i]; + uint256 balance = balances[address(asset)]; + if (balance > 0) _availableRedemptionAssets += assetRegistry.convertToUnitOfAccount(asset, balance); + } + } + + /** + * @notice Transfers a specified amount of redemption assets to a given address. + * @param to The recipient address of the assets. + * @param amount The amount of assets to transfer. + * @dev Requires the caller to be the redeemer and the contract to not be paused. + * @dev Iterates over the supported assets, transferring each asset's balance to the user until fully depleted. + */ + function transferRedemptionAssets(address to, uint256 amount, bytes calldata /* data */) public onlyRedeemer whenNotPaused nonReentrant { + uint256 balance = availableRedemptionAssets(); + if (balance < amount) revert InsufficientAssetBalance(ETH_ASSET, amount, balance); + + uint256 amountTransferred = amount; + IERC20[] memory assets = assetRegistry.getAssets(); + for (uint256 i = 0; i < assets.length; ++i) { + IERC20 asset = assets[i]; + uint256 assetBalance = balances[address(asset)]; + if (assetBalance > 0) { + uint256 assetBalanceInUnit = assetRegistry.convertToUnitOfAccount(asset, assetBalance); + if (assetBalanceInUnit >= amount) { + uint256 reqAmountInAsset = assetRegistry.convertFromUnitOfAccount(asset, amount); + IERC20(asset).safeTransfer(to, reqAmountInAsset); + balances[address(asset)] -= reqAmountInAsset; + emit AssetTransferred(address(asset), msg.sender, to, reqAmountInAsset); + break; + } else { + IERC20(asset).safeTransfer(to, assetBalance); + balances[address(asset)] = 0; + amount -= assetBalanceInUnit; + emit AssetTransferred(address(asset), msg.sender, to, assetBalance); + } + } + } + emit TotalAssetsTransferred(ETH_ASSET, msg.sender, to, amountTransferred); + } + + /** + * @notice Withdraws a specified amount of redemption assets and processes them through ynETH. + * @param amount The amount of ETH to withdraw and process. + * @dev Requires the caller to be the redeemer and the contract to not be paused. + */ + function withdrawRedemptionAssets(uint256 amount) public onlyRedeemer whenNotPaused nonReentrant { + IERC20[] memory assets = assetRegistry.getAssets(); + for (uint256 i = 0; i < assets.length; ++i) { + IERC20 asset = assets[i]; + uint256 assetBalance = balances[address(asset)]; + if (assetBalance > 0) { + uint256 assetBalanceInUnit = assetRegistry.convertToUnitOfAccount(asset, assetBalance); + if (assetBalanceInUnit >= amount) { + uint256 reqAmountInAsset = assetRegistry.convertFromUnitOfAccount(asset, amount); + ynEigen.processWithdrawn(reqAmountInAsset, address(asset)); + balances[address(asset)] -= reqAmountInAsset; + emit AssetWithdrawn(address(asset), msg.sender, address(ynEigen), reqAmountInAsset); + break; + } else { + ynEigen.processWithdrawn(assetBalance, address(asset)); + balances[address(asset)] = 0; + amount -= assetBalanceInUnit; + emit AssetWithdrawn(address(asset), msg.sender, address(ynEigen), assetBalance); + } + } + } + emit TotalAssetsTransferred(ETH_ASSET, msg.sender, address(ynEigen), amount); + } + + //-------------------------------------------------------------------------------------- + //---------------------------------- MODIFIERS --------------------------------------- + //-------------------------------------------------------------------------------------- + + /** + * @notice Ensure that the given address is not the zero address. + * @param _address The address to check. + */ + modifier notZeroAddress(address _address) { + if (_address == address(0)) { + revert ZeroAddress(); + } + _; + } + + /** + * @notice Checks if the contract is not paused. + */ + modifier whenNotPaused() { + if (paused) { + revert ContractPaused(); + } + _; + } + + /** + * @notice Ensures that the caller has the REDEEMER_ROLE. + */ + modifier onlyRedeemer() { + if (msg.sender != redeemer) { + revert NotRedeemer(msg.sender); + } + _; + } + + //-------------------------------------------------------------------------------------- + //---------------------------------- PAUSE FUNCTIONS --------------------------------- + //-------------------------------------------------------------------------------------- + + /** + * @notice Pauses the contract, preventing certain actions. + */ + function pause() external onlyRole(PAUSER_ROLE) { + if (paused) revert ContractPaused(); + + paused = true; + + emit Paused(); + } + + /** + * @notice Unpauses the contract, allowing certain actions. + */ + function unpause() external onlyRole(UNPAUSER_ROLE) { + if (!paused) revert ContractUnpaused(); + + paused = false; + + emit Unpaused(); + } +} diff --git a/src/ynEIGEN/TokenStakingNode.sol b/src/ynEIGEN/TokenStakingNode.sol index 084ca071b..421b6643a 100644 --- a/src/ynEIGEN/TokenStakingNode.sol +++ b/src/ynEIGEN/TokenStakingNode.sol @@ -12,6 +12,9 @@ import {IDelegationManager} from "lib/eigenlayer-contracts/src/contracts/interfa import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; import {ITokenStakingNode} from "src/interfaces/ITokenStakingNode.sol"; import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; +import {IWrapper} from "src/interfaces/IWrapper.sol"; +import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; + interface ITokenStakingNodeEvents { event DepositToEigenlayer( @@ -22,6 +25,9 @@ interface ITokenStakingNodeEvents { ); event Delegated(address indexed operator, bytes32 approverSalt); event Undelegated(bytes32[] withdrawalRoots); + event QueuedWithdrawals(IStrategy strategies, uint256 shares, bytes32[] fullWithdrawalRoots); + event CompletedQueuedWithdrawals(uint256 shares, uint256 amountOut, address strategy); + event DeallocatedTokens(uint256 amount, IERC20 token); } /** @@ -45,6 +51,8 @@ contract TokenStakingNode is error NotTokenStakingNodeOperator(); error NotStrategyManager(); error NotTokenStakingNodeDelegator(); + error NotTokenStakingNodesWithdrawer(); + error ArrayLengthMismatch(); //-------------------------------------------------------------------------------------- //---------------------------------- VARIABLES --------------------------------------- @@ -53,6 +61,9 @@ contract TokenStakingNode is ITokenStakingNodesManager public override tokenStakingNodesManager; uint256 public nodeId; + mapping(IStrategy => uint256) public queuedShares; + mapping(IERC20 => uint256) public withdrawn; + //-------------------------------------------------------------------------------------- //---------------------------------- INITIALIZATION ---------------------------------- //-------------------------------------------------------------------------------------- @@ -88,10 +99,15 @@ contract TokenStakingNode is uint256[] calldata amounts, IStrategy[] calldata strategies ) external nonReentrant onlyYieldNestStrategyManager { + + uint256 assetsLength = assets.length; + if (assetsLength != amounts.length || assetsLength != strategies.length) { + revert ArrayLengthMismatch(); + } + IStrategyManager strategyManager = tokenStakingNodesManager .strategyManager(); - uint256 assetsLength = assets.length; for (uint256 i = 0; i < assetsLength; i++) { IERC20 asset = assets[i]; uint256 amount = amounts[i]; @@ -108,6 +124,129 @@ contract TokenStakingNode is } } + //-------------------------------------------------------------------------------------- + //-------------------------------- EIGENLAYER WITHDRAWALS ----------------------------- + //-------------------------------------------------------------------------------------- + + function getQueuedSharesAndWithdrawn(IStrategy _strategy, IERC20 _asset) external view returns (uint256, uint256) { + return (queuedShares[_strategy], withdrawn[_asset]); + } + + /** + * @notice Queues withdrawals for a specific strategy + * @param _strategy The strategy from which to withdraw + * @param _shares The number of shares to withdraw + * @return _fullWithdrawalRoots An array of withdrawal roots generated by the queueWithdrawals operation + */ + function queueWithdrawals( + IStrategy _strategy, + uint256 _shares + ) external onlyTokenStakingNodesWithdrawer returns (bytes32[] memory _fullWithdrawalRoots) { + + IStrategy[] memory _strategiesArray = new IStrategy[](1); + _strategiesArray[0] = _strategy; + uint256[] memory _sharesArray = new uint256[](1); + _sharesArray[0] = _shares; + IDelegationManager.QueuedWithdrawalParams[] memory _params = new IDelegationManager.QueuedWithdrawalParams[](1); + _params[0] = IDelegationManager.QueuedWithdrawalParams({ + strategies: _strategiesArray, + shares: _sharesArray, + withdrawer: address(this) + }); + + queuedShares[_strategy] += _shares; + + _fullWithdrawalRoots = tokenStakingNodesManager.delegationManager().queueWithdrawals(_params); + + emit QueuedWithdrawals(_strategy, _shares, _fullWithdrawalRoots); + } + + /** + * @notice Completes queued withdrawals for a specific strategy + * @param _nonce The nonce of the withdrawal + * @param _startBlock The block number when the withdrawal was queued + * @param _shares The number of shares to withdraw + * @param _strategy The strategy from which to withdraw + * @param _middlewareTimesIndexes The indexes of middleware times to use for the withdrawal + * @param updateTokenStakingNodesBalances If true calls updateTokenStakingNodesBalances for yieldNestStrategyManager + */ + function completeQueuedWithdrawals( + uint256 _nonce, + uint32 _startBlock, + uint256 _shares, + IStrategy _strategy, + uint256[] memory _middlewareTimesIndexes, + bool updateTokenStakingNodesBalances + ) public onlyTokenStakingNodesWithdrawer { + + IDelegationManager _delegationManager = tokenStakingNodesManager.delegationManager(); + + IDelegationManager.Withdrawal[] memory _withdrawals = new IDelegationManager.Withdrawal[](1); + { + IStrategy[] memory _strategiesArray = new IStrategy[](1); + _strategiesArray[0] = _strategy; + uint256[] memory _sharesArray = new uint256[](1); + _sharesArray[0] = _shares; + _withdrawals[0] = IDelegationManager.Withdrawal({ + staker: address(this), + delegatedTo: _delegationManager.delegatedTo(address(this)), + withdrawer: address(this), + nonce: _nonce, + startBlock: _startBlock, + strategies: _strategiesArray, + shares: _sharesArray + }); + } + + IERC20 _token = _strategy.underlyingToken(); + uint256 _balanceBefore = _token.balanceOf(address(this)); + + { + bool[] memory _receiveAsTokens = new bool[](1); + _receiveAsTokens[0] = true; + IERC20[][] memory _tokens = new IERC20[][](1); + _tokens[0] = new IERC20[](1); + _tokens[0][0] = _token; + + _delegationManager.completeQueuedWithdrawals( + _withdrawals, + _tokens, + _middlewareTimesIndexes, + _receiveAsTokens + ); + } + + uint256 _actualAmountOut = _token.balanceOf(address(this)) - _balanceBefore; + IWrapper _wrapper = IYieldNestStrategyManager(tokenStakingNodesManager.yieldNestStrategyManager()).wrapper(); + IERC20(_token).forceApprove(address(_wrapper), _actualAmountOut); // NOTE: approving also token that will not be transferred + (_actualAmountOut, _token) = _wrapper.wrap(_actualAmountOut, _token); + + queuedShares[_strategy] -= _shares; + withdrawn[_token] += _actualAmountOut; + + if (updateTokenStakingNodesBalances) { + // Actual balance changes only if slashing occured. choose to update here + // only if the off-chain considers it necessary to save gas + IYieldNestStrategyManager(tokenStakingNodesManager.yieldNestStrategyManager()).updateTokenStakingNodesBalances( + _token + ); + } + + emit CompletedQueuedWithdrawals(_shares, _actualAmountOut, address(_strategy)); + } + + /** + * @notice Deallocates tokens from the withdrawn balance and approves them for transfer. + * @param _token The ERC20 token to deallocate. + * @param _amount The amount of tokens to deallocate. + */ + function deallocateTokens(IERC20 _token, uint256 _amount) external onlyYieldNestStrategyManager { + withdrawn[_token] -= _amount; + _token.safeTransfer(msg.sender, _amount); + + emit DeallocatedTokens(_amount, _token); + } + //-------------------------------------------------------------------------------------- //---------------------------------- DELEGATION -------------------------------------- //-------------------------------------------------------------------------------------- @@ -169,6 +308,13 @@ contract TokenStakingNode is _; } + modifier onlyTokenStakingNodesWithdrawer() { + if ( + !IYieldNestStrategyManager(tokenStakingNodesManager.yieldNestStrategyManager()).isStakingNodesWithdrawer(msg.sender) + ) revert NotTokenStakingNodesWithdrawer(); + _; + } + //-------------------------------------------------------------------------------------- //---------------------------------- BEACON IMPLEMENTATION --------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/ynEIGEN/TokenStakingNodesManager.sol b/src/ynEIGEN/TokenStakingNodesManager.sol index 992682933..d9eabd977 100644 --- a/src/ynEIGEN/TokenStakingNodesManager.sol +++ b/src/ynEIGEN/TokenStakingNodesManager.sol @@ -30,11 +30,8 @@ contract TokenStakingNodesManager is AccessControlUpgradeable, ITokenStakingNode //---------------------------------- ERRORS ------------------------------------------ //-------------------------------------------------------------------------------------- - error UnsupportedAsset(IERC20 asset); error Unauthorized(); error InsufficientFunds(); - error Paused(); - error ZeroAmount(); error ZeroAddress(); error BeaconImplementationAlreadyExists(); error NoBeaconImplementationExists(); @@ -126,7 +123,6 @@ contract TokenStakingNodesManager is AccessControlUpgradeable, ITokenStakingNode maxNodeCount = init.maxNodeCount; } - //-------------------------------------------------------------------------------------- //---------------------------------- STAKING NODE CREATION --------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/ynEIGEN/ynEigen.sol b/src/ynEIGEN/ynEigen.sol index 57924de17..c68c11232 100644 --- a/src/ynEIGEN/ynEigen.sol +++ b/src/ynEIGEN/ynEigen.sol @@ -7,6 +7,7 @@ import {ReentrancyGuardUpgradeable} from "lib/openzeppelin-contracts-upgradeable import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IynEigen} from "src/interfaces/IynEigen.sol"; import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; +import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; import {ynBase} from "src/ynBase.sol"; @@ -17,6 +18,7 @@ interface IynEigenEvents { event LSDStakingNodeCreated(uint256 nodeId, address nodeAddress); event MaxNodeCountUpdated(uint256 maxNodeCount); event DepositsPausedUpdated(bool paused); + event WithdrawProcessed(uint256 amount, uint256 newBalance, address asset); } contract ynEigen is IynEigen, ynBase, ReentrancyGuardUpgradeable, IynEigenEvents { @@ -40,6 +42,13 @@ contract ynEigen is IynEigen, ynBase, ReentrancyGuardUpgradeable, IynEigenEvents error NotStrategyManager(address msgSender); error InsufficientAssetBalance(IERC20 asset, uint256 balance, uint256 requestedAmount); error ZeroShares(); + error CallerNotAuthorized(); + + //-------------------------------------------------------------------------------------- + //---------------------------------- ROLES -------------------------------------------- + //-------------------------------------------------------------------------------------- + + bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); //-------------------------------------------------------------------------------------- //---------------------------------- VARIABLES --------------------------------------- @@ -203,6 +212,37 @@ contract ynEigen is IynEigen, ynBase, ReentrancyGuardUpgradeable, IynEigenEvents } } + //-------------------------------------------------------------------------------------- + //---------------------------------- WITHDRAWALS -------------------------------------- + //-------------------------------------------------------------------------------------- + + function burn(uint256 amount) external onlyRole(BURNER_ROLE) { + _burn(msg.sender, amount); + } + + function previewRedeem(IERC20 asset, uint256 shares) external view returns (uint256) { + return convertToAssets(asset, shares); + } + + function previewRedeem(uint256 shares) external view returns (uint256) { + return _convertToAssets(shares, Math.Rounding.Floor); + } + + function convertToAssets(IERC20 asset, uint256 shares) public view returns (uint256) { + if (!assetIsSupported(asset)) { + revert UnsupportedAsset(asset); + } + return assetRegistry.convertFromUnitOfAccount(asset, _convertToAssets(shares, Math.Rounding.Floor)); + } + + function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view returns (uint256) { + + uint256 supply = totalSupply(); + if (supply == 0) return shares; + + return Math.mulDiv(shares, totalAssets(), supply, rounding); + } + //-------------------------------------------------------------------------------------- //---------------------------------- TOTAL ASSETS ----------------------------------- //-------------------------------------------------------------------------------------- @@ -280,6 +320,23 @@ contract ynEigen is IynEigen, ynBase, ReentrancyGuardUpgradeable, IynEigenEvents } } + function processWithdrawn(uint256 _amount, address _asset) public { + if (_amount == 0) revert ZeroAmount(); + + IYieldNestStrategyManager _yieldNestStrategyManager = IYieldNestStrategyManager(yieldNestStrategyManager); + if ( + msg.sender != address(_yieldNestStrategyManager) && + msg.sender != address(_yieldNestStrategyManager.redemptionAssetsVault()) + ) revert CallerNotAuthorized(); + + uint256 _newBalance = assets[_asset].balance + _amount; + assets[_asset].balance = _newBalance; + + IERC20(_asset).safeTransferFrom(msg.sender, address(this), _amount); + + emit WithdrawProcessed(_amount, _newBalance, _asset); + } + //-------------------------------------------------------------------------------------- //---------------------------------- PAUSING ----------------------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/ynEIGEN/ynEigenDepositAdapter.sol b/src/ynEIGEN/ynEigenDepositAdapter.sol index 2e5a709f9..21d574336 100644 --- a/src/ynEIGEN/ynEigenDepositAdapter.sol +++ b/src/ynEIGEN/ynEigenDepositAdapter.sol @@ -10,6 +10,8 @@ import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/ import {AccessControlUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol"; import {Initializable} from "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import {IWrapper} from "src/interfaces/IWrapper.sol"; + interface IynEigenDepositAdapterEvents { event ReferralDepositProcessed( address sender, @@ -54,6 +56,7 @@ contract ynEigenDepositAdapter is IynEigenDepositAdapterEvents, Initializable, A IERC4626 public woETH; IERC20 public stETH; IERC20 public oETH; + IWrapper public wrapper; //-------------------------------------------------------------------------------------- //---------------------------------- INITIALIZATION ---------------------------------- @@ -84,6 +87,10 @@ contract ynEigenDepositAdapter is IynEigenDepositAdapterEvents, Initializable, A oETH = IERC20(woETH.asset()); } + function initializeV2(address _wrapper) external reinitializer(2) notZeroAddress(_wrapper) { + wrapper = IWrapper(_wrapper); + } + /** * @notice Handles the deposit of assets into the ynEigen system. It supports all assets supported by ynEigen @@ -159,8 +166,8 @@ contract ynEigenDepositAdapter is IynEigenDepositAdapterEvents, Initializable, A function depositStETH(uint256 amount, address receiver) internal returns (uint256 shares) { stETH.safeTransferFrom(msg.sender, address(this), amount); - stETH.forceApprove(address(wstETH), amount); - uint256 wstETHAmount = wstETH.wrap(amount); + stETH.forceApprove(address(wrapper), amount); + (uint256 wstETHAmount,) = wrapper.wrap(amount, stETH); wstETH.forceApprove(address(ynEigen), wstETHAmount); shares = ynEigen.deposit(IERC20(address(wstETH)), wstETHAmount, receiver); @@ -170,8 +177,8 @@ contract ynEigenDepositAdapter is IynEigenDepositAdapterEvents, Initializable, A function depositOETH(uint256 amount, address receiver) internal returns (uint256 shares) { oETH.safeTransferFrom(msg.sender, address(this), amount); - oETH.forceApprove(address(woETH), amount); - uint256 woETHShares = woETH.deposit(amount, address(this)); + oETH.forceApprove(address(wrapper), amount); + (uint256 woETHShares,) = wrapper.wrap(amount, oETH); woETH.forceApprove(address(ynEigen), woETHShares); shares = ynEigen.deposit(IERC20(address(woETH)), woETHShares, receiver); diff --git a/src/ynEIGEN/ynEigenViewer.sol b/src/ynEIGEN/ynEigenViewer.sol index 32a528b9e..9b36485ed 100644 --- a/src/ynEIGEN/ynEigenViewer.sol +++ b/src/ynEIGEN/ynEigenViewer.sol @@ -12,14 +12,37 @@ import {IEigenStrategyManager} from "../interfaces/IEigenStrategyManager.sol"; contract ynEigenViewer { + + //-------------------------------------------------------------------------------------- + //---------------------------------- STRUCTS ----------------------------------------- + //-------------------------------------------------------------------------------------- struct AssetInfo { address asset; string name; string symbol; + uint256 rate; uint256 ratioOfTotalAssets; - uint256 totalBalance; + uint256 totalBalanceInUnitOfAccount; + uint256 totalBalanceInAsset; } + + //-------------------------------------------------------------------------------------- + //---------------------------------- ERRORS ------------------------------------------ + //-------------------------------------------------------------------------------------- + + error ArrayLengthMismatch(uint256 expected, uint256 actual); + + //-------------------------------------------------------------------------------------- + //---------------------------------- CONSTANTS --------------------------------------- + //-------------------------------------------------------------------------------------- + + uint256 public constant DECIMALS = 1_000_000; + uint256 public constant UNIT = 1 ether; + + //-------------------------------------------------------------------------------------- + //---------------------------------- VARIABLES --------------------------------------- + //-------------------------------------------------------------------------------------- /* solhint-disable immutable-vars-naming */ AssetRegistry public immutable assetRegistry; @@ -28,8 +51,9 @@ contract ynEigenViewer { IRateProvider public immutable rateProvider; /* solhint-enable immutable-vars-naming */ - uint256 public constant DECIMALS = 1_000_000; - uint256 public constant UNIT = 1 ether; + //-------------------------------------------------------------------------------------- + //---------------------------------- INITIALIZATION ---------------------------------- + //-------------------------------------------------------------------------------------- constructor(address _assetRegistry, address _ynEIGEN, address _tokenStakingNodesManager, address _rateProvider) { assetRegistry = AssetRegistry(_assetRegistry); @@ -38,24 +62,45 @@ contract ynEigenViewer { rateProvider = IRateProvider(_rateProvider); } + /** + * @notice Retrieves all staking nodes from the TokenStakingNodesManager + * @dev This function calls the getAllNodes() function of the tokenStakingNodesManager contract + * @return An array of ITokenStakingNode interfaces representing all staking nodes + */ function getAllStakingNodes() external view returns (ITokenStakingNode[] memory) { return tokenStakingNodesManager.getAllNodes(); } + /** + * @notice Retrieves information about all assets in the ynEigen system + * @dev This function fetches asset data from the asset registry and ynEigen system + * and computes various metrics for each asset + * @return _assetsInfo An array of AssetInfo structs containing detailed information about each asset + */ function getYnEigenAssets() external view returns (AssetInfo[] memory _assetsInfo) { IERC20[] memory _assets = assetRegistry.getAssets(); uint256 _assetsLength = _assets.length; _assetsInfo = new AssetInfo[](_assetsLength); + uint256[] memory assetBalances = assetRegistry.getAllAssetBalances(); + // Assert that the lengths of _assets and assetBalances are the same + if (_assetsLength != assetBalances.length) { + revert ArrayLengthMismatch(_assetsLength, assetBalances.length); + } + uint256 _totalAssets = ynEIGEN.totalAssets(); + for (uint256 i = 0; i < _assetsLength; ++i) { - uint256 _balance = assetRegistry.convertToUnitOfAccount(_assets[i], ynEIGEN.assetBalance(_assets[i])); + uint256 assetBalance = assetBalances[i]; + uint256 _balance = assetRegistry.convertToUnitOfAccount(_assets[i], assetBalance); _assetsInfo[i] = AssetInfo({ asset: address(_assets[i]), name: IERC20Metadata(address(_assets[i])).name(), symbol: IERC20Metadata(address(_assets[i])).symbol(), + rate: rateProvider.rate(address(_assets[i])), ratioOfTotalAssets: (_balance > 0 && _totalAssets > 0) ? _balance * DECIMALS / _totalAssets : 0, - totalBalance: _balance + totalBalanceInUnitOfAccount: _balance, + totalBalanceInAsset: assetBalance }); } } diff --git a/test/integration/ynEIGEN/AssetRegistry.t.sol b/test/integration/ynEIGEN/AssetRegistry.t.sol index 47f261ec5..bb3b4fa05 100644 --- a/test/integration/ynEIGEN/AssetRegistry.t.sol +++ b/test/integration/ynEIGEN/AssetRegistry.t.sol @@ -174,6 +174,48 @@ contract AssetRegistryTest is ynEigenIntegrationBaseTest { assertEq(convertedAmount, expectedConvertedAmount, "Converted amount should match expected value based on real rate"); } + function testWSTETHconvertFromUnitOfAccountFuzz(uint256 amount) public { + vm.assume(amount < 1000000 ether); + + IERC20 asset = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); // Using wstETH as the asset + uint256 realRate = IstETH(chainAddresses.lsd.STETH_ADDRESS).getPooledEthByShares(1e18); + uint256 expectedConvertedAmount = amount * 1e18 / realRate; // Calculating the expected converted amount based on the real rate + uint256 convertedAmount = assetRegistry.convertFromUnitOfAccount(asset, amount); + assertEq(convertedAmount, expectedConvertedAmount, "Converted amount should match expected value based on real rate"); + } + + function testsfrxETHconvertFromUnitOfAccountFuzz(uint256 amount) public { + vm.assume(amount < 1000000 ether); + + IERC20 asset = IERC20(chainAddresses.lsd.SFRXETH_ADDRESS); // Using wstETH as the asset + address FRAX_ASSET = chainAddresses.lsd.SFRXETH_ADDRESS; + IFrxEthWethDualOracle FRX_ETH_WETH_DUAL_ORACLE = IFrxEthWethDualOracle(testAssetUtils.FRX_ETH_WETH_DUAL_ORACLE()); + uint256 realRate = IsfrxETH(FRAX_ASSET).pricePerShare() * FRX_ETH_WETH_DUAL_ORACLE.getCurveEmaEthPerFrxEth() / 1e18; + uint256 expectedConvertedAmount = amount * 1e18 / realRate; // Calculating the expected converted amount based on the real rate + uint256 convertedAmount = assetRegistry.convertFromUnitOfAccount(asset, amount); + assertEq(convertedAmount, expectedConvertedAmount, "Converted amount should match expected value based on real rate"); + } + + function testRETHconvertFromUnitOfAccountFuzz(uint256 amount) public { + vm.assume(amount < 1000000 ether); + + IERC20 asset = IERC20(chainAddresses.lsd.RETH_ADDRESS); // Using rETH as the asset + uint256 realRate = IrETH(chainAddresses.lsd.RETH_ADDRESS).getExchangeRate(); + uint256 expectedConvertedAmount = amount * 1e18 / realRate; // Calculating the expected converted amount based on the real rate + uint256 convertedAmount = assetRegistry.convertFromUnitOfAccount(asset, amount); + assertEq(convertedAmount, expectedConvertedAmount, "Converted amount should match expected value based on real rate"); + } + + function testWOETHconvertFromUnitOfAccountFuzz(uint256 amount) public { + vm.assume(amount < 1000000 ether); + + IERC20 asset = IERC20(chainAddresses.lsd.WOETH_ADDRESS); // Using woETH as the asset + uint256 realRate = IERC4626(chainAddresses.lsd.WOETH_ADDRESS).previewRedeem(1e18); + uint256 expectedConvertedAmount = amount * 1e18 / realRate; // Calculating the expected converted amount based on the real rate + uint256 convertedAmount = assetRegistry.convertFromUnitOfAccount(asset, amount); + assertEq(convertedAmount, expectedConvertedAmount, "Converted amount should match expected value based on real rate"); + } + function testPauseActions() public { vm.prank(actors.ops.PAUSE_ADMIN); assetRegistry.pauseActions(); diff --git a/test/integration/ynEIGEN/TokenStakingNode.t.sol b/test/integration/ynEIGEN/TokenStakingNode.t.sol index 1f63d8194..f235a7091 100644 --- a/test/integration/ynEIGEN/TokenStakingNode.t.sol +++ b/test/integration/ynEIGEN/TokenStakingNode.t.sol @@ -11,10 +11,99 @@ import {ISignatureUtils} from "lib/eigenlayer-contracts/src/contracts/interfaces import {TestAssetUtils} from "test/utils/TestAssetUtils.sol"; import {ITokenStakingNode} from "src/interfaces/ITokenStakingNode.sol"; import {IwstETH} from "src/external/lido/IwstETH.sol"; +import {EigenStrategyManager} from "src/ynEIGEN/EigenStrategyManager.sol"; +import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; +import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; + + import "forge-std/console.sol"; +interface ITestState { + function ynEigenToken() external view returns (IynEigen); + function tokenStakingNodesManager() external view returns (ITokenStakingNodesManager); + function assetRegistry() external view returns (IAssetRegistry); + function eigenStrategyManager() external view returns (EigenStrategyManager); + function eigenLayerStrategyManager() external view returns (IStrategyManager); + function eigenLayerDelegationManager() external view returns (IDelegationManager); +} + +interface ITokenStakingNodesManager { + function nodes(uint256 nodeId) external view returns (ITokenStakingNode); + function createTokenStakingNode() external returns (ITokenStakingNode); +} + + +struct StateSnapshot { + uint256 totalAssets; + uint256 totalSupply; + mapping(IStrategy => uint256) strategyQueuedShares; + mapping(address => uint256) withdrawnByToken; + mapping(address => uint256) stakedAssetBalanceForNode; + mapping(address => uint256) strategySharesForNode; +} + +contract NodeStateSnapshot { + StateSnapshot public snapshot; + + constructor() {} + + function takeSnapshot(address testAddress, uint256 nodeId) external { + + ITestState state = ITestState(testAddress); + ITokenStakingNode node = state.tokenStakingNodesManager().nodes(nodeId); + + snapshot.totalAssets = state.ynEigenToken().totalAssets(); + snapshot.totalSupply = state.ynEigenToken().totalSupply(); + + IERC20[] memory assets = state.assetRegistry().getAssets(); + + for (uint256 i = 0; i < assets.length; i++) { + IERC20 asset = assets[i]; + IStrategy strategy = state.eigenStrategyManager().strategies(asset); + + // Store queued shares for each strategy + snapshot.strategyQueuedShares[strategy] = node.queuedShares(strategy); + + // Store withdrawn amount for each token + snapshot.withdrawnByToken[address(asset)] = node.withdrawn(asset); + + // Store staked asset balance for each token + snapshot.stakedAssetBalanceForNode[address(asset)] + = state.eigenStrategyManager().getStakedAssetBalanceForNode(asset, nodeId); + + // Store strategy shares for each token + snapshot.strategySharesForNode[address(asset)] = + state.eigenStrategyManager().strategyManager().stakerStrategyShares(address(node), strategy); + } + } + + function totalAssets() external view returns (uint256) { + return snapshot.totalAssets; + } + + function totalSupply() external view returns (uint256) { + return snapshot.totalSupply; + } + + function getStrategyQueuedShares(IStrategy strategy) external view returns (uint256) { + return snapshot.strategyQueuedShares[strategy]; + } + + function getWithdrawnByToken(address token) external view returns (uint256) { + return snapshot.withdrawnByToken[token]; + } + + function getStakedAssetBalanceForNode(address token) external view returns (uint256) { + return snapshot.stakedAssetBalanceForNode[token]; + } + + function getStrategySharesForNode(address token) external view returns (uint256) { + return snapshot.strategySharesForNode[token]; + } +} + contract TokenStakingNodeTest is ynEigenIntegrationBaseTest { ITokenStakingNode tokenStakingNode; @@ -104,6 +193,180 @@ contract TokenStakingNodeTest is ynEigenIntegrationBaseTest { vm.expectRevert("Pausable: index is paused"); eigenStrategyManager.stakeAssetsToNode(nodeId, assets, amounts); } + + + function testTokenQueueWithdrawals() public { + + uint256 wstethAmount = 100 ether; + IERC20 wstETH = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); + uint256 nodeId = tokenStakingNode.nodeId(); + { + // 1. Obtain wstETH and Deposit assets to ynEigen by User + testAssetUtils.depositAsset(ynEigenToken, address(wstETH), wstethAmount, address(this)); + + // 2. Deposit assets to Eigenlayer by Token Staking Node + + IERC20[] memory assets = new IERC20[](1); + assets[0] = wstETH; + uint256[] memory amounts = new uint256[](1); + amounts[0] = wstethAmount; + vm.prank(actors.ops.STRATEGY_CONTROLLER); + eigenStrategyManager.stakeAssetsToNode(nodeId, assets, amounts); + } + + NodeStateSnapshot before = new NodeStateSnapshot(); + before.takeSnapshot(address(this), nodeId); + + uint256 withdrawnShares = 50 ether; + + // 3. Queue withdrawals + vm.startPrank(actors.ops.STAKING_NODES_WITHDRAWER); + tokenStakingNode.queueWithdrawals( + eigenStrategyManager.strategies(wstETH), + withdrawnShares + ); + vm.stopPrank(); + + NodeStateSnapshot afterQueued = new NodeStateSnapshot(); + afterQueued.takeSnapshot(address(this), nodeId); + + // Assert queuedShares increased + assertEq( + afterQueued.getStrategyQueuedShares(eigenStrategyManager.strategies(wstETH)), + before.getStrategyQueuedShares(eigenStrategyManager.strategies(wstETH)) + withdrawnShares, + "Queued shares should have increased" + ); + + // Assert everything else stayed the same + assertEq( + afterQueued.totalAssets(), + before.totalAssets(), + "Total assets should not have changed" + ); + assertEq( + afterQueued.totalSupply(), + before.totalSupply(), + "Total supply should not have changed" + ); + assertEq( + afterQueued.getWithdrawnByToken(address(wstETH)), + before.getWithdrawnByToken(address(wstETH)), + "Withdrawn amount should not have changed" + ); + + // Assert staked asset balance decreased + assertApproxEqAbs( + afterQueued.getStakedAssetBalanceForNode(address(wstETH)), + before.getStakedAssetBalanceForNode(address(wstETH)), + 10, + "Staked asset balance should have decreased by withdrawn shares" + ); + + // Assert strategy shares decreased + assertEq( + afterQueued.getStrategySharesForNode(address(wstETH)), + before.getStrategySharesForNode(address(wstETH)) - withdrawnShares, + "Strategy shares should have decreased by withdrawn shares" + ); + } + + function testQueueAndCompleteWithdrawals() public { + + // Stake some wstETH to the node + uint256 stakeAmount = 100 ether; + IERC20 wstETH = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); + uint256 nodeId = tokenStakingNode.nodeId(); + uint256 sharesToWithdraw; + uint256 withdrawAmount; + IStrategy wstETHStrategy = eigenStrategyManager.strategies(wstETH); + uint32 _startBlock; + { + // 1. Obtain wstETH and Deposit assets to ynEigen by User + testAssetUtils.depositAsset(ynEigenToken, address(wstETH), stakeAmount, address(this)); + + IERC20[] memory assets = new IERC20[](1); + assets[0] = IERC20(address(wstETH)); + uint256[] memory amounts = new uint256[](1); + amounts[0] = stakeAmount; + + vm.prank(actors.ops.STRATEGY_CONTROLLER); + eigenStrategyManager.stakeAssetsToNode(nodeId, assets, amounts); + + // Prepare for withdrawal + withdrawAmount = stakeAmount / 2; + sharesToWithdraw = wstETHStrategy.underlyingToShares( + IwstETH(address(wstETH)).getStETHByWstETH(withdrawAmount) + ); + + // Queue withdrawal + vm.prank(actors.ops.STAKING_NODES_WITHDRAWER); + tokenStakingNode.queueWithdrawals(wstETHStrategy, sharesToWithdraw); + + _startBlock = uint32(block.number); + + IStrategy[] memory _strategies = new IStrategy[](1); + _strategies[0] = wstETHStrategy; + vm.roll(block.number + eigenLayer.delegationManager.getWithdrawalDelay(_strategies)); + } + + // Capture state before completing withdrawal + NodeStateSnapshot before = new NodeStateSnapshot(); + before.takeSnapshot(address(this), nodeId); + + // Complete queued withdrawal + vm.startPrank(actors.ops.STAKING_NODES_WITHDRAWER); + tokenStakingNode.completeQueuedWithdrawals( + eigenLayer.delegationManager.cumulativeWithdrawalsQueued(address(tokenStakingNode)) - 1, // _nonce + _startBlock, // _startBlock + sharesToWithdraw, // _shares + wstETHStrategy, // _strategy + new uint256[](1), // _middlewareTimesIndexes + false + ); + vm.stopPrank(); + + NodeStateSnapshot afterCompletion = new NodeStateSnapshot(); + afterCompletion.takeSnapshot(address(this), nodeId); + + // Assert withdrawn amount increased + assertApproxEqAbs( + afterCompletion.getWithdrawnByToken(address(wstETH)), + before.getWithdrawnByToken(address(wstETH)) + withdrawAmount, + 3, + "Withdrawn amount should have increased by withdrawAmount" + ); + + // Assert queued shares decreased + assertEq( + afterCompletion.getStrategyQueuedShares(wstETHStrategy), + before.getStrategyQueuedShares(wstETHStrategy) - sharesToWithdraw, + "Queued shares should have decreased by sharesToWithdraw" + ); + + // Assert total supply remained unchanged + assertEq( + afterCompletion.totalSupply(), + before.totalSupply(), + "Total supply should remain unchanged" + ); + + // Assert total assets remained approximately unchanged + assertApproxEqAbs( + afterCompletion.totalAssets(), + before.totalAssets(), + 3, + "Total assets should remain approximately unchanged" + ); + + eigenStrategyManager.updateTokenStakingNodesBalances(wstETH); + + assertApproxEqAbs( + afterCompletion.totalAssets(), + ynEigenToken.totalAssets(), + 3, + "Total assets should have decreased by approximately the withdraw amount" + ); + } } @@ -189,4 +452,5 @@ contract TokenStakingNodeDelegate is ynEigenIntegrationBaseTest { address delegatedAddress = delegationManager.delegatedTo(address(tokenStakingNodeInstance)); assertEq(delegatedAddress, address(0), "Delegation should be cleared after undelegation."); } -} \ No newline at end of file +} + diff --git a/test/integration/ynEIGEN/ynEigen.t.sol b/test/integration/ynEIGEN/ynEigen.t.sol index ab9af3085..ffd9ac863 100644 --- a/test/integration/ynEIGEN/ynEigen.t.sol +++ b/test/integration/ynEIGEN/ynEigen.t.sol @@ -320,6 +320,80 @@ contract ynEigenTest is ynEigenIntegrationBaseTest { uint256 ethAmount = assetRegistry.convertToUnitOfAccount(asset, amount); assertEq(ethAmount, expectedETHAmount, "convertToEth does not match expected value"); } + + function testPreviewRedeemWSTETH(uint256 amount) public { + vm.assume( + amount < 10000 ether && amount >= 10 wei + ); + + IERC20 asset = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); + + uint256 wstethPrice = rateProvider.rate(chainAddresses.lsd.WSTETH_ADDRESS); + + uint256 expectedRedeemPreview = amount * 1e18 / wstethPrice; + uint256 previewRedeem = ynEigenToken.previewRedeem(asset, amount); + assertEq(previewRedeem, expectedRedeemPreview, "testPreviewRedeemWSTETH: E0"); + } + + function testPreviewRedeemWOETH(uint256 amount) public { + vm.assume( + amount < 10000 ether && amount >= 10 wei + ); + + IERC20 asset = IERC20(chainAddresses.lsd.WOETH_ADDRESS); + + uint256 woethPrice = rateProvider.rate(chainAddresses.lsd.WOETH_ADDRESS); + + uint256 expectedRedeemPreview = amount * 1e18 / woethPrice; + uint256 previewRedeem = ynEigenToken.previewRedeem(asset, amount); + assertEq(previewRedeem, expectedRedeemPreview, "testPreviewRedeemWOETH: E0"); + } + + function testPreviewRedeemSFRXETH(uint256 amount) public { + vm.assume( + amount < 10000 ether && amount >= 10 wei + ); + + IERC20 asset = IERC20(chainAddresses.lsd.SFRXETH_ADDRESS); + + uint256 sfrxETHPrice = rateProvider.rate(chainAddresses.lsd.SFRXETH_ADDRESS); + + uint256 expectedRedeemPreview = amount * 1e18 / sfrxETHPrice; + uint256 previewRedeem = ynEigenToken.previewRedeem(asset, amount); + assertEq(previewRedeem, expectedRedeemPreview, "testPreviewRedeemSFRXETH: E0"); + } + + function testPreviewRedeemRETH(uint256 amount) public { + vm.assume( + amount < 10000 ether && amount >= 10 wei + ); + + IERC20 asset = IERC20(chainAddresses.lsd.RETH_ADDRESS); + + uint256 rethPrice = rateProvider.rate(chainAddresses.lsd.RETH_ADDRESS); + + uint256 expectedRedeemPreview = amount * 1e18 / rethPrice; + uint256 previewRedeem = ynEigenToken.previewRedeem(asset, amount); + assertEq(previewRedeem, expectedRedeemPreview, "testPreviewRedeemRETH: E0"); + } + + function testPreviewRedeemNoAssets(uint256 amount) public { + vm.assume( + amount < 10000 ether && amount >= 10 wei + ); + + assertEq(amount, ynEigenToken.previewRedeem(amount), "testPreviewRedeemNoAssets: E0"); + } + + function testPreviewRedeemUnknownAsset() public { + // Use a random address as an unknown asset + address unknownAsset = address(0x1234567890123456789012345678901234567890); + uint256 amount = 1 ether; + + // Expect the function to revert with UnsupportedAsset error + vm.expectRevert(abi.encodeWithSelector(ynEigen.UnsupportedAsset.selector, unknownAsset)); + ynEigenToken.previewRedeem(IERC20(unknownAsset), amount); + } } contract ynTransferPauseTest is ynEigenIntegrationBaseTest { diff --git a/test/integration/ynEIGEN/ynEigenIntegrationBaseTest.sol b/test/integration/ynEIGEN/ynEigenIntegrationBaseTest.sol index 2a442b343..d31ecb23f 100644 --- a/test/integration/ynEIGEN/ynEigenIntegrationBaseTest.sol +++ b/test/integration/ynEIGEN/ynEigenIntegrationBaseTest.sol @@ -22,7 +22,11 @@ import {Utils} from "script/Utils.sol"; import {ActorAddresses} from "script/Actors.sol"; import {TestAssetUtils} from "test/utils/TestAssetUtils.sol"; import {LSDRateProvider} from "src/ynEIGEN/LSDRateProvider.sol"; +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; +import {IRedeemableAsset} from "src/interfaces/IRedeemableAsset.sol"; import {IynEigen} from "src/interfaces/IynEigen.sol"; import {IRateProvider} from "src/interfaces/IRateProvider.sol"; import {IAssetRegistry} from "src/interfaces/IAssetRegistry.sol"; @@ -62,9 +66,12 @@ contract ynEigenIntegrationBaseTest is Test, Utils { AssetRegistry public assetRegistry; LSDRateProvider public rateProvider; ynEigenDepositAdapter public ynEigenDepositAdapterInstance; + RedemptionAssetsVault public redemptionAssetsVault; + WithdrawalQueueManager public withdrawalQueueManager; + LSDWrapper public wrapper; // Strategy - EigenStrategyManager eigenStrategyManager; + EigenStrategyManager public eigenStrategyManager; // Eigen struct EigenLayer { @@ -92,7 +99,7 @@ contract ynEigenIntegrationBaseTest is Test, Utils { setupEigenLayer(); setupTokenStakingNodesManager(); setupYnEigen(); - setupEigenStrategyManagerAndAssetRegistry(); + setupYieldNestAssets(); setupYnEigenDepositAdapter(); } @@ -209,7 +216,7 @@ contract ynEigenIntegrationBaseTest is Test, Utils { tokenStakingNodesManager.registerTokenStakingNode(address(tokenStakingNodeImplementation)); } - function setupEigenStrategyManagerAndAssetRegistry() public { + function setupYieldNestAssets() public { IERC20[] memory lsdAssets = new IERC20[](5); IStrategy[] memory strategies = new IStrategy[](5); @@ -270,6 +277,77 @@ contract ynEigenIntegrationBaseTest is Test, Utils { assetManagerRole: actors.admin.ASSET_MANAGER }); assetRegistry.initialize(assetRegistryInit); + + // deploy RedemptionAssetsVault + { + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address(new RedemptionAssetsVault()), + actors.admin.PROXY_ADMIN_OWNER, + "" + ); + redemptionAssetsVault = RedemptionAssetsVault(payable(address(_proxy))); + } + + // deploy WithdrawalQueueManager + { + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address(new WithdrawalQueueManager()), + actors.admin.PROXY_ADMIN_OWNER, + "" + ); + withdrawalQueueManager = WithdrawalQueueManager(address(_proxy)); + } + + // deploy wrapper + { + // call `initialize` on LSDWrapper + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address( + new LSDWrapper( + chainAddresses.lsd.WSTETH_ADDRESS, + chainAddresses.lsd.WOETH_ADDRESS, + chainAddresses.lsd.OETH_ADDRESS, + chainAddresses.lsd.STETH_ADDRESS) + ), + actors.admin.PROXY_ADMIN_OWNER, + abi.encodeWithSignature("initialize()") + ); + wrapper = LSDWrapper(address(_proxy)); + } + + // initialize eigenStrategyManager + { + eigenStrategyManager.initializeV2(address(redemptionAssetsVault), address(wrapper), actors.ops.WITHDRAWAL_MANAGER); + } + + // initialize RedemptionAssetsVault + { + RedemptionAssetsVault.Init memory _init = RedemptionAssetsVault.Init({ + admin: actors.admin.PROXY_ADMIN_OWNER, + redeemer: address(withdrawalQueueManager), + ynEigen: ynEigenToken, + assetRegistry: assetRegistry + }); + redemptionAssetsVault.initialize(_init); + } + + // initialize WithdrawalQueueManager + { + WithdrawalQueueManager.Init memory _init = WithdrawalQueueManager.Init({ + name: "ynLSDe Withdrawal Manager", + symbol: "ynLSDeWM", + redeemableAsset: IRedeemableAsset(address(ynEigenToken)), + redemptionAssetsVault: redemptionAssetsVault, + admin: actors.admin.PROXY_ADMIN_OWNER, + withdrawalQueueAdmin: actors.ops.WITHDRAWAL_MANAGER, + redemptionAssetWithdrawer: actors.ops.REDEMPTION_ASSET_WITHDRAWER, + requestFinalizer: actors.ops.REQUEST_FINALIZER, + // withdrawalFee: 500, // 0.05% + withdrawalFee: 0, + feeReceiver: actors.admin.FEE_RECEIVER + }); + withdrawalQueueManager.initialize(_init); + } } function setupYnEigenDepositAdapter() public { @@ -281,6 +359,7 @@ contract ynEigenIntegrationBaseTest is Test, Utils { }); vm.prank(actors.admin.PROXY_ADMIN_OWNER); ynEigenDepositAdapterInstance.initialize(ynEigenDepositAdapterInit); + ynEigenDepositAdapterInstance.initializeV2(address(wrapper)); } } diff --git a/test/integration/ynEIGEN/ynEigenViewer.t.sol b/test/integration/ynEIGEN/ynEigenViewer.t.sol index c8d2992ae..bc7e66df3 100644 --- a/test/integration/ynEIGEN/ynEigenViewer.t.sol +++ b/test/integration/ynEIGEN/ynEigenViewer.t.sol @@ -4,17 +4,29 @@ pragma solidity 0.8.24; import {IERC20, IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ITokenStakingNodesManager,ITokenStakingNode} from "../../../src/interfaces/ITokenStakingNodesManager.sol"; - +import {TestAssetUtils} from "test/utils/TestAssetUtils.sol"; import {ynEigenViewer} from "../../../src/ynEIGEN/ynEigenViewer.sol"; import {console} from "forge-std/console.sol"; import "./ynEigenIntegrationBaseTest.sol"; + + interface IAssetRegistryView { function assets() external view returns (IERC20Metadata[] memory); } contract ynEigenViewerTest is ynEigenIntegrationBaseTest { + TestAssetUtils testAssetUtils; + address[10] public depositors; + + constructor() { + testAssetUtils = new TestAssetUtils(); + for (uint i = 0; i < 10; i++) { + depositors[i] = address(uint160(uint256(keccak256(abi.encodePacked("depositor", i))))); + } + } + ynEigenViewer private _ynEigenViewer; function setUp() public override { @@ -42,10 +54,138 @@ contract ynEigenViewerTest is ynEigenIntegrationBaseTest { assertEq(_assetsInfo[i].name, IERC20Metadata(address(_assets[i])).name(), "testGetYnEigenAssets: E2"); assertEq(_assetsInfo[i].symbol, IERC20Metadata(address(_assets[i])).symbol(), "testGetYnEigenAssets: E3"); assertEq(_assetsInfo[i].ratioOfTotalAssets, 0, "testGetYnEigenAssets: E4"); - assertEq(_assetsInfo[i].totalBalance, 0, "testGetYnEigenAssets: E5"); + assertEq(_assetsInfo[i].totalBalanceInUnitOfAccount, 0, "testGetYnEigenAssets: E5"); + assertEq(_assetsInfo[i].totalBalanceInAsset, 0, "testGetYnEigenAssets: E5"); } } + function testGetYnEigenAssetsAfterDeposits() public { + // Define deposit amounts + uint256 sfrxEthAmount = 1 ether; + uint256 wstEthAmount = 0.5 ether; + uint256 rEthAmount = 0.75 ether; + + // Create a user for deposits + address user = makeAddr("userXYZ"); + + // Make deposits to the user + deal(address(chainAddresses.lsd.SFRXETH_ADDRESS), user, sfrxEthAmount); + deal(address(chainAddresses.lsd.WSTETH_ADDRESS), user, wstEthAmount); + deal(address(chainAddresses.lsd.RETH_ADDRESS), user, rEthAmount); + + // Switch to user context + vm.startPrank(user); + + // Approve and deposit tokens + IERC20(chainAddresses.lsd.SFRXETH_ADDRESS).approve(address(ynEigenToken), sfrxEthAmount); + IERC20(chainAddresses.lsd.WSTETH_ADDRESS).approve(address(ynEigenToken), wstEthAmount); + IERC20(chainAddresses.lsd.RETH_ADDRESS).approve(address(ynEigenToken), rEthAmount); + + ynEigenToken.deposit(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS), sfrxEthAmount, user); + ynEigenToken.deposit(IERC20(chainAddresses.lsd.WSTETH_ADDRESS), wstEthAmount, user); + ynEigenToken.deposit(IERC20(chainAddresses.lsd.RETH_ADDRESS), rEthAmount, user); + + // End user context + vm.stopPrank(); + + + // Get asset info after deposits + ynEigenViewer.AssetInfo[] memory assetsInfo = _ynEigenViewer.getYnEigenAssets(); + + { + vm.startPrank(actors.ops.STAKING_NODE_CREATOR); + tokenStakingNodesManager.createTokenStakingNode(); + tokenStakingNodesManager.createTokenStakingNode(); + vm.stopPrank(); + + EigenStrategyManager.NodeAllocation[] memory allocations = new EigenStrategyManager.NodeAllocation[](2); + IERC20[] memory assets1 = new IERC20[](1); + uint256[] memory amounts1 = new uint256[](1); + assets1[0] = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); + amounts1[0] = wstEthAmount / 4; + + testAssetUtils.depositAsset(ynEigenToken, address(assets1[0]), amounts1[0], depositors[0]); + + IERC20[] memory assets2 = new IERC20[](1); + uint256[] memory amounts2 = new uint256[](1); + assets2[0] = IERC20(chainAddresses.lsd.RETH_ADDRESS); + amounts2[0] = rEthAmount / 4; + + testAssetUtils.depositAsset(ynEigenToken, address(assets2[0]), amounts2[0], depositors[1]); + + allocations[0] = EigenStrategyManager.NodeAllocation(0, assets1, amounts1); + allocations[1] = EigenStrategyManager.NodeAllocation(1, assets2, amounts2); + + uint256 totalAssetsBefore = ynEigenToken.totalAssets(); + + vm.startPrank(actors.ops.STRATEGY_CONTROLLER); + eigenStrategyManager.stakeAssetsToNodes(allocations); + vm.stopPrank(); + + assertApproxEqRel(ynEigenToken.totalAssets(), totalAssetsBefore, 1e16, "Total assets should not change significantly after staking"); + } + + // Calculate the value of each deposit in ETH and its expected ratio + uint256 sfrxEthValueInEth = assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS), sfrxEthAmount); + uint256 wstEthValueInEth = assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.WSTETH_ADDRESS), wstEthAmount); + uint256 rEthValueInEth = assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.RETH_ADDRESS), rEthAmount); + + uint256 totalValueInEth = sfrxEthValueInEth + wstEthValueInEth + rEthValueInEth; + + uint256 expectedSfrxEthRatio = (sfrxEthValueInEth * 1e6) / totalValueInEth; + uint256 expectedWstEthRatio = (wstEthValueInEth * 1e6) / totalValueInEth; + uint256 expectedREthRatio = (rEthValueInEth * 1e6) / totalValueInEth; + + // Verify that the sum of total values in ETH matches totalAssets + uint256 summedTotalValueInEth = sfrxEthValueInEth + wstEthValueInEth + rEthValueInEth; + assertApproxEqRel( + summedTotalValueInEth, + ynEigenToken.totalAssets(), + 1e18, + "Sum of asset values in ETH should approximately equal totalAssets" + ); + + // Verify asset info + for (uint256 i = 0; i < assetsInfo.length; i++) { + if (assetsInfo[i].asset == address(chainAddresses.lsd.SFRXETH_ADDRESS)) { + assertEq(assetsInfo[i].name, "Staked Frax Ether", "Incorrect sfrxETH name"); + assertEq(assetsInfo[i].symbol, "sfrxETH", "Incorrect sfrxETH symbol"); + assertEq(assetsInfo[i].totalBalanceInUnitOfAccount, sfrxEthValueInEth, "Incorrect sfrxETH balance in unit of account"); + assertEq(assetsInfo[i].totalBalanceInAsset, sfrxEthAmount, "Incorrect sfrxETH balance in asset"); + assertApproxEqRel(assetsInfo[i].ratioOfTotalAssets, expectedSfrxEthRatio, 1e16, "Incorrect sfrxETH ratio"); + assertEq(assetsInfo[i].rate, rateProvider.rate(address(chainAddresses.lsd.SFRXETH_ADDRESS)), "sfrxETH rate mismatch with rateProvider"); + } else if (assetsInfo[i].asset == address(chainAddresses.lsd.WSTETH_ADDRESS)) { + assertEq(assetsInfo[i].name, "Wrapped liquid staked Ether 2.0", "Incorrect wstETH name"); + assertEq(assetsInfo[i].symbol, "wstETH", "Incorrect wstETH symbol"); + assertEq(assetsInfo[i].totalBalanceInUnitOfAccount, wstEthValueInEth, "Incorrect wstETH balance in unit of account"); + assertEq(assetsInfo[i].totalBalanceInAsset, wstEthAmount, "Incorrect wstETH balance in asset"); + assertApproxEqRel(assetsInfo[i].ratioOfTotalAssets, expectedWstEthRatio, 1e16, "Incorrect wstETH ratio"); + assertEq(assetsInfo[i].rate, rateProvider.rate(address(chainAddresses.lsd.WSTETH_ADDRESS)), "wstETH rate mismatch with rateProvider"); + } else if (assetsInfo[i].asset == address(chainAddresses.lsd.RETH_ADDRESS)) { + assertEq(assetsInfo[i].name, "Rocket Pool ETH", "Incorrect rETH name"); + assertEq(assetsInfo[i].symbol, "rETH", "Incorrect rETH symbol"); + assertEq(assetsInfo[i].totalBalanceInUnitOfAccount, rEthValueInEth, "Incorrect rETH balance in unit of account"); + assertEq(assetsInfo[i].totalBalanceInAsset, rEthAmount, "Incorrect rETH balance in asset"); + assertApproxEqRel(assetsInfo[i].ratioOfTotalAssets, expectedREthRatio, 1e16, "Incorrect rETH ratio"); + assertEq(assetsInfo[i].rate, rateProvider.rate(address(chainAddresses.lsd.RETH_ADDRESS)), "rETH rate mismatch with rateProvider"); + } else { + assertEq(assetsInfo[i].totalBalanceInUnitOfAccount, 0, "Non-zero balance for undeposited asset in unit of account"); + assertEq(assetsInfo[i].totalBalanceInAsset, 0, "Non-zero balance for undeposited asset in asset"); + assertEq(assetsInfo[i].ratioOfTotalAssets, 0, "Non-zero ratio for undeposited asset"); + assertEq(assetsInfo[i].rate, rateProvider.rate(assetsInfo[i].asset), "Rate mismatch with rateProvider for undeposited asset"); + } + } + + // Calculate the sum of all ratios + uint256 totalRatio = 0; + for (uint256 i = 0; i < assetsInfo.length; i++) { + totalRatio += assetsInfo[i].ratioOfTotalAssets; + } + + // Assert that the sum of all ratios is approximately equal to 1e6 (100%) + assertApproxEqRel(totalRatio, 1e6, 1e18, "Sum of all asset ratios should be approximately 1e6 (100%)"); + } + function testPreviewDepositStETH() public { // Set up test amount uint256 testAmount = 1 ether; diff --git a/test/scenarios/ynEIGEN/UpgradeTestTemp.t.sol b/test/scenarios/ynEIGEN/UpgradeTestTemp.t.sol new file mode 100644 index 000000000..987ce4c4b --- /dev/null +++ b/test/scenarios/ynEIGEN/UpgradeTestTemp.t.sol @@ -0,0 +1,59 @@ +// // SPDX-License-Identifier: BSD 3-Clause License +// pragma solidity ^0.8.24; + +// import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; + +// import "forge-std/Test.sol"; + +// contract SmallTest is Test { + +// address _proxy = 0x58c721D3f6FcdE97ef07df793D359DbCc1fDB36d; +// address _newImplementation = 0xD82d61C2905595f554233De5cDb947979802267C; +// address _ynSecurityCouncil = 0x743b91CDB1C694D4F51bCDA3a4A59DcC0d02b913; +// TimelockController timelockController = TimelockController(payable(0x317f96879FA387aFF6dfFAAc4A09bD2f6e367801)); + +// function setUp() public {} + +// function testSmall() public { +// bytes memory _data = abi.encodeWithSignature( +// "upgradeAndCall(address,address,bytes)", +// _proxy, // proxy +// _newImplementation, // implementation +// "" +// ); +// console.logBytes(_data); +// console.log("15 minutes: ", 15 minutes); +// console.logBytes32(bytes32(0)); +// vm.startPrank(_ynSecurityCouncil); +// timelockController.schedule( +// // getTransparentUpgradeableProxyAdminAddress(_proxyAddress), // target +// 0x3BE30C73AF6b1c5d6d13E20B41D89a81FC074211, +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0), // salt +// timelockController.getMinDelay() // delay +// ); +// vm.stopPrank(); + +// uint256 minDelay; +// if (block.chainid == 1) { // Mainnet +// minDelay = 3 days; +// } else if (block.chainid == 17000) { // Holesky +// minDelay = 15 minutes; +// } else { +// revert("Unsupported chain ID"); +// } +// skip(minDelay); + +// vm.startPrank(_ynSecurityCouncil); +// timelockController.execute( +// 0x3BE30C73AF6b1c5d6d13E20B41D89a81FC074211, // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0) // salt +// ); +// vm.stopPrank(); +// } +// } \ No newline at end of file diff --git a/test/scenarios/ynEIGEN/ynLSDeDepositAdapter.t.sol b/test/scenarios/ynEIGEN/ynLSDeDepositAdapter.t.sol new file mode 100644 index 000000000..062ba3134 --- /dev/null +++ b/test/scenarios/ynEIGEN/ynLSDeDepositAdapter.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {TestAssetUtils} from "test/utils/TestAssetUtils.sol"; + +import "./ynLSDeWithdrawals.t.sol"; + +contract ynLSDeDepositAdapterTest is ynLSDeWithdrawalsTest { + + TestAssetUtils public testAssetUtils; + + function setUp() public override { + super.setUp(); + + // deploy testAssetUtils + { + testAssetUtils = new TestAssetUtils(); + } + } + + function testDepositSTETH(uint256 _amount) public { + vm.assume(_amount > 10_000 && _amount <= 10 ether); + + testAssetUtils.get_stETH(user, _amount); + + vm.startPrank(user); + IERC20(chainAddresses.lsd.STETH_ADDRESS).approve(address(ynEigenDepositAdapter_), _amount); + uint256 _ynOut = ynEigenDepositAdapter_.deposit(IERC20(chainAddresses.lsd.STETH_ADDRESS), _amount, user); + vm.stopPrank(); + + assertEq(IERC20(yneigen).balanceOf(user), _ynOut, "testDepositSTETH"); + } + + function testDepositOETH(uint256 _amount) public { + vm.assume(_amount > 10_000 && _amount <= 10 ether); + + testAssetUtils.get_OETH(user, _amount + 10); + + vm.startPrank(user); + IERC20(chainAddresses.lsd.OETH_ADDRESS).approve(address(ynEigenDepositAdapter_), _amount); + uint256 _ynOut = ynEigenDepositAdapter_.deposit(IERC20(chainAddresses.lsd.OETH_ADDRESS), _amount, user); + vm.stopPrank(); + + assertEq(IERC20(yneigen).balanceOf(user), _ynOut, "testDepositOETH"); + } +} \ No newline at end of file diff --git a/test/scenarios/ynEIGEN/ynLSDeUpgradeScenario.sol b/test/scenarios/ynEIGEN/ynLSDeUpgradeScenario.sol index 5dfc8956a..33c3ee246 100644 --- a/test/scenarios/ynEIGEN/ynLSDeUpgradeScenario.sol +++ b/test/scenarios/ynEIGEN/ynLSDeUpgradeScenario.sol @@ -1,375 +1,380 @@ -// SPDX-License-Identifier: BSD 3-Clause License -pragma solidity ^0.8.24; +// // SPDX-License-Identifier: BSD 3-Clause License +// pragma solidity ^0.8.24; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +// import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +// import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +// import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {ITokenStakingNode} from "../../../src/interfaces/ITokenStakingNode.sol"; +// import {ITokenStakingNode} from "../../../src/interfaces/ITokenStakingNode.sol"; -import {HoleskyLSDRateProvider} from "../../../src/testnet/HoleksyLSDRateProvider.sol"; +// import {HoleskyLSDRateProvider} from "../../../src/testnet/HoleksyLSDRateProvider.sol"; -import {TestStakingNodesManagerV2} from "../../mocks/TestStakingNodesManagerV2.sol"; -import {TestStakingNodeV2} from "../../mocks/TestStakingNodeV2.sol"; +// import {TestStakingNodesManagerV2} from "../../mocks/TestStakingNodesManagerV2.sol"; +// // import {TestStakingNodeV2} from "../../mocks/TestStakingNodeV2.sol"; +// import {TokenStakingNode} from "../../../src/ynEIGEN/TokenStakingNode.sol"; -import "./ynLSDeScenarioBaseTest.sol"; -import {console} from "forge-std/console.sol"; +// import "./ynLSDeScenarioBaseTest.sol"; +// import {console} from "forge-std/console.sol"; -contract ynLSDeUpgradeScenario is ynLSDeScenarioBaseTest { +// contract ynLSDeUpgradeScenario is ynLSDeScenarioBaseTest { + +// function setUp() public virtual override { +// super.setUp(); +// } - function test_Upgrade_ynLSDe_Scenario() public { +// function test_Upgrade_ynLSDe_Scenario() public { - address previousImplementation = getTransparentUpgradeableProxyImplementationAddress(address(yneigen)); - console.log("Total assets before upgrade:", yneigen.totalAssets()); - address newImplementation = address(new ynEigen()); +// address previousImplementation = getTransparentUpgradeableProxyImplementationAddress(address(yneigen)); +// console.log("Total assets before upgrade:", yneigen.totalAssets()); +// address newImplementation = address(new ynEigen()); - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(yneigen), newImplementation); +// upgradeContract(address(yneigen), newImplementation); - runUpgradeInvariants(address(yneigen), previousImplementation, newImplementation); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(yneigen)); - } +// runUpgradeInvariants(address(yneigen), previousImplementation, newImplementation); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(yneigen)); +// } - function test_Upgrade_TokenStakingNodesManager_Scenario() public { +// function test_Upgrade_TokenStakingNodesManager_Scenario() public { - address previousStakingNodesManagerImpl = getTransparentUpgradeableProxyImplementationAddress(address(tokenStakingNodesManager)); - address newStakingNodesManagerImpl = address(new TokenStakingNodesManager()); +// address previousStakingNodesManagerImpl = getTransparentUpgradeableProxyImplementationAddress(address(tokenStakingNodesManager)); +// address newStakingNodesManagerImpl = address(new TokenStakingNodesManager()); - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(tokenStakingNodesManager), newStakingNodesManagerImpl); +// upgradeContract(address(tokenStakingNodesManager), newStakingNodesManagerImpl); - runUpgradeInvariants(address(tokenStakingNodesManager), previousStakingNodesManagerImpl, newStakingNodesManagerImpl); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(tokenStakingNodesManager)); - } +// runUpgradeInvariants(address(tokenStakingNodesManager), previousStakingNodesManagerImpl, newStakingNodesManagerImpl); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(tokenStakingNodesManager)); +// } - function test_Upgrade_AssetRegistry() public { +// function test_Upgrade_AssetRegistry() public { - address previousAssetRegistryImpl = getTransparentUpgradeableProxyImplementationAddress(address(assetRegistry)); - address newAssetRegistryImpl = address(new AssetRegistry()); +// address previousAssetRegistryImpl = getTransparentUpgradeableProxyImplementationAddress(address(assetRegistry)); +// address newAssetRegistryImpl = address(new AssetRegistry()); - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(assetRegistry), newAssetRegistryImpl); +// upgradeContract(address(assetRegistry), newAssetRegistryImpl); - runUpgradeInvariants(address(assetRegistry), previousAssetRegistryImpl, newAssetRegistryImpl); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(assetRegistry)); - } +// runUpgradeInvariants(address(assetRegistry), previousAssetRegistryImpl, newAssetRegistryImpl); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(assetRegistry)); +// } - function test_Upgrade_EigenStrategyManager() public { +// function test_Upgrade_EigenStrategyManager() public { - address previousEigenStrategyManagerImpl = getTransparentUpgradeableProxyImplementationAddress(address(eigenStrategyManager)); - address newEigenStrategyManagerImpl = address(new EigenStrategyManager()); +// address previousEigenStrategyManagerImpl = getTransparentUpgradeableProxyImplementationAddress(address(eigenStrategyManager)); +// address newEigenStrategyManagerImpl = address(new EigenStrategyManager()); - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(eigenStrategyManager), newEigenStrategyManagerImpl); +// upgradeContract(address(eigenStrategyManager), newEigenStrategyManagerImpl); - runUpgradeInvariants(address(eigenStrategyManager), previousEigenStrategyManagerImpl, newEigenStrategyManagerImpl); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(eigenStrategyManager)); - } +// runUpgradeInvariants(address(eigenStrategyManager), previousEigenStrategyManagerImpl, newEigenStrategyManagerImpl); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(eigenStrategyManager)); +// } - function test_Upgrade_LSDRateProvider() public { +// function test_Upgrade_LSDRateProvider() public { - address previousLSDRateProviderImpl = getTransparentUpgradeableProxyImplementationAddress(address(lsdRateProvider)); - address newLSDRateProviderImpl; - if (block.chainid == 17000) { // Holesky - newLSDRateProviderImpl = address(new HoleskyLSDRateProvider()); - } else if (block.chainid == 1) { // Mainnet - newLSDRateProviderImpl = address(new LSDRateProvider()); - } else { - revert("Unsupported chain ID"); - } +// address previousLSDRateProviderImpl = getTransparentUpgradeableProxyImplementationAddress(address(lsdRateProvider)); +// address newLSDRateProviderImpl; +// if (block.chainid == 17000) { // Holesky +// newLSDRateProviderImpl = address(new HoleskyLSDRateProvider()); +// } else if (block.chainid == 1) { // Mainnet +// newLSDRateProviderImpl = address(new LSDRateProvider()); +// } else { +// revert("Unsupported chain ID"); +// } - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(lsdRateProvider), newLSDRateProviderImpl); +// upgradeContract(address(lsdRateProvider), newLSDRateProviderImpl); - runUpgradeInvariants(address(lsdRateProvider), previousLSDRateProviderImpl, newLSDRateProviderImpl); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(lsdRateProvider)); - } +// runUpgradeInvariants(address(lsdRateProvider), previousLSDRateProviderImpl, newLSDRateProviderImpl); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(lsdRateProvider)); +// } - function test_Upgrade_ynEigenDepositAdapter() public { +// function test_Upgrade_ynEigenDepositAdapter() public { - address previousYnEigenDepositAdapterImpl = getTransparentUpgradeableProxyImplementationAddress(address(ynEigenDepositAdapter_)); - address newYnEigenDepositAdapterImpl = address(new ynEigenDepositAdapter()); +// address previousYnEigenDepositAdapterImpl = getTransparentUpgradeableProxyImplementationAddress(address(ynEigenDepositAdapter_)); +// address newYnEigenDepositAdapterImpl = address(new ynEigenDepositAdapter()); - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - upgradeContract(address(ynEigenDepositAdapter_), newYnEigenDepositAdapterImpl); +// upgradeContract(address(ynEigenDepositAdapter_), newYnEigenDepositAdapterImpl); - runUpgradeInvariants(address(ynEigenDepositAdapter_), previousYnEigenDepositAdapterImpl, newYnEigenDepositAdapterImpl); - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(ynEigenDepositAdapter_)); - } - - function test_Upgrade_AllContracts_Batch() public { - address[] memory contracts = new address[](6); - address[] memory newImplementations = new address[](6); - - // YnLSDe - contracts[0] = address(yneigen); - newImplementations[0] = address(new ynEigen()); - - // EigenStrategyManager - contracts[1] = address(eigenStrategyManager); - newImplementations[1] = address(new EigenStrategyManager()); - - // LSDRateProvider - if (block.chainid == 17000) { // Holesky - newImplementations[2] = address(new HoleskyLSDRateProvider()); - } else if (block.chainid == 1) { // Mainnet - newImplementations[2] = address(new LSDRateProvider()); - } else { - revert("Unsupported chain ID"); - } - contracts[2] = address(lsdRateProvider); - - // ynEigenDepositAdapter - contracts[3] = address(ynEigenDepositAdapter_); - newImplementations[3] = address(new ynEigenDepositAdapter()); - - // AssetRegistry - contracts[4] = address(assetRegistry); - newImplementations[4] = address(new AssetRegistry()); - - // TokenStakingNodesManager - contracts[5] = address(tokenStakingNodesManager); - newImplementations[5] = address(new TokenStakingNodesManager()); - - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - - address[] memory previousImplementations = new address[](contracts.length); - for (uint i = 0; i < contracts.length; i++) { - previousImplementations[i] = getTransparentUpgradeableProxyImplementationAddress(contracts[i]); - } - - upgradeContractBatch(contracts, newImplementations); - - for (uint i = 0; i < contracts.length; i++) { - runUpgradeInvariants(contracts[i], previousImplementations[i], newImplementations[i]); - runTransferOwnership(contracts[i]); - } - - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - } - - function test_Upgrade_TokenStakingNodeImplementation_Scenario() public { - - ITokenStakingNode[] memory tokenStakingNodesBefore = tokenStakingNodesManager.getAllNodes(); - - uint256 previousTotalAssets = yneigen.totalAssets(); - uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); - - TestStakingNodeV2 testStakingNodeV2 = new TestStakingNodeV2(); - { - bytes memory _data = abi.encodeWithSignature( - "upgradeTokenStakingNode(address)", - payable(testStakingNodeV2) - ); - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.schedule( - address(tokenStakingNodesManager), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0), // salt - timelockController.getMinDelay() // delay - ); - vm.stopPrank(); - - uint256 minDelay; - if (block.chainid == 1) { // Mainnet - minDelay = 3 days; - } else if (block.chainid == 17000) { // Holesky - minDelay = 15 minutes; - } else { - revert("Unsupported chain ID"); - } - skip(minDelay); - - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.execute( - address(tokenStakingNodesManager), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0) // salt - ); - vm.stopPrank(); - } +// runUpgradeInvariants(address(ynEigenDepositAdapter_), previousYnEigenDepositAdapterImpl, newYnEigenDepositAdapterImpl); +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(ynEigenDepositAdapter_)); +// } + +// function test_Upgrade_AllContracts_Batch() public { +// address[] memory contracts = new address[](6); +// address[] memory newImplementations = new address[](6); + +// // YnLSDe +// contracts[0] = address(yneigen); +// newImplementations[0] = address(new ynEigen()); + +// // EigenStrategyManager +// contracts[1] = address(eigenStrategyManager); +// newImplementations[1] = address(new EigenStrategyManager()); + +// // LSDRateProvider +// if (block.chainid == 17000) { // Holesky +// newImplementations[2] = address(new HoleskyLSDRateProvider()); +// } else if (block.chainid == 1) { // Mainnet +// newImplementations[2] = address(new LSDRateProvider()); +// } else { +// revert("Unsupported chain ID"); +// } +// contracts[2] = address(lsdRateProvider); + +// // ynEigenDepositAdapter +// contracts[3] = address(ynEigenDepositAdapter_); +// newImplementations[3] = address(new ynEigenDepositAdapter()); + +// // AssetRegistry +// contracts[4] = address(assetRegistry); +// newImplementations[4] = address(new AssetRegistry()); + +// // TokenStakingNodesManager +// contracts[5] = address(tokenStakingNodesManager); +// newImplementations[5] = address(new TokenStakingNodesManager()); + +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); + +// address[] memory previousImplementations = new address[](contracts.length); +// for (uint i = 0; i < contracts.length; i++) { +// previousImplementations[i] = getTransparentUpgradeableProxyImplementationAddress(contracts[i]); +// } + +// upgradeContractBatch(contracts, newImplementations); + +// for (uint i = 0; i < contracts.length; i++) { +// runUpgradeInvariants(contracts[i], previousImplementations[i], newImplementations[i]); +// runTransferOwnership(contracts[i]); +// } + +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// } + +// function test_Upgrade_TokenStakingNodeImplementation_Scenario() public { + +// ITokenStakingNode[] memory tokenStakingNodesBefore = tokenStakingNodesManager.getAllNodes(); + +// uint256 previousTotalAssets = yneigen.totalAssets(); +// uint256 previousTotalSupply = IERC20(address(yneigen)).totalSupply(); + +// TokenStakingNode testStakingNodeV2 = new TokenStakingNode(); +// { +// bytes memory _data = abi.encodeWithSignature( +// "upgradeTokenStakingNode(address)", +// testStakingNodeV2 +// ); +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.schedule( +// address(tokenStakingNodesManager), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0), // salt +// timelockController.getMinDelay() // delay +// ); +// vm.stopPrank(); + +// uint256 minDelay; +// if (block.chainid == 1) { // Mainnet +// minDelay = 3 days; +// } else if (block.chainid == 17000) { // Holesky +// minDelay = 15 minutes; +// } else { +// revert("Unsupported chain ID"); +// } +// skip(minDelay); + +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.execute( +// address(tokenStakingNodesManager), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0) // salt +// ); +// vm.stopPrank(); +// } - UpgradeableBeacon beacon = tokenStakingNodesManager.upgradeableBeacon(); - address upgradedImplementationAddress = beacon.implementation(); - assertEq(upgradedImplementationAddress, payable(testStakingNodeV2)); - - // check tokenStakingNodesManager.getAllNodes is the same as before - ITokenStakingNode[] memory tokenStakingNodesAfter = tokenStakingNodesManager.getAllNodes(); - assertEq(tokenStakingNodesAfter.length, tokenStakingNodesBefore.length, "TokenStakingNodes length mismatch after upgrade"); - for (uint i = 0; i < tokenStakingNodesAfter.length; i++) { - assertEq(address(tokenStakingNodesAfter[i]), address(tokenStakingNodesBefore[i]), "TokenStakingNode address mismatch after upgrade"); - } - - runSystemStateInvariants(previousTotalAssets, previousTotalSupply); - runTransferOwnership(address(tokenStakingNodesManager)); - } - - function runUpgradeInvariants( - address proxyAddress, - address previousImplementation, - address newImplementation - ) internal { - // Check that the new implementation address is correctly set - address currentImplementation = getTransparentUpgradeableProxyImplementationAddress(proxyAddress); - assertEq(currentImplementation, newImplementation, "Invariant: Implementation address should match the new implementation address"); - // Ensure the implementation address has actually changed - assertNotEq(previousImplementation, newImplementation, "Invariant: New implementation should be different from the previous one"); - } - - function runSystemStateInvariants(uint256 previousTotalAssets, uint256 previousTotalSupply) public { - uint256 threshold = previousTotalAssets / 1e3; - assertTrue(compareWithThreshold(yneigen.totalAssets(), previousTotalAssets, threshold), "Total assets integrity check failed"); - assertEq(yneigen.totalSupply(), previousTotalSupply, "Share mint integrity check failed"); - } - - function upgradeContractBatch(address[] memory _proxyAddresses, address[] memory _newImplementations) public { - require(_proxyAddresses.length == _newImplementations.length, "Arrays must have the same length"); - - address[] memory targets = new address[](_proxyAddresses.length); - uint256[] memory values = new uint256[](_proxyAddresses.length); - bytes[] memory payloads = new bytes[](_proxyAddresses.length); - - for (uint i = 0; i < _proxyAddresses.length; i++) { - targets[i] = getTransparentUpgradeableProxyAdminAddress(_proxyAddresses[i]); - values[i] = 0; - payloads[i] = abi.encodeWithSignature( - "upgradeAndCall(address,address,bytes)", - _proxyAddresses[i], - _newImplementations[i], - "" - ); - } - - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.scheduleBatch( - targets, - values, - payloads, - bytes32(0), // predecessor - bytes32(0), // salt - timelockController.getMinDelay() // delay - ); - vm.stopPrank(); - - uint256 minDelay; - if (block.chainid == 1) { // Mainnet - minDelay = 3 days; - } else if (block.chainid == 17000) { // Holesky - minDelay = 15 minutes; - } else { - revert("Unsupported chain ID"); - } - skip(minDelay); - - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.executeBatch( - targets, - values, - payloads, - bytes32(0), // predecessor - bytes32(0) // salt - ); - vm.stopPrank(); - } - - function upgradeContract(address _proxyAddress, address _newImplementation) public { - bytes memory _data = abi.encodeWithSignature( - "upgradeAndCall(address,address,bytes)", - _proxyAddress, // proxy - _newImplementation, // implementation - "" // no data - ); - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.schedule( - getTransparentUpgradeableProxyAdminAddress(_proxyAddress), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0), // salt - timelockController.getMinDelay() // delay - ); - vm.stopPrank(); - - uint256 minDelay; - if (block.chainid == 1) { // Mainnet - minDelay = 3 days; - } else if (block.chainid == 17000) { // Holesky - minDelay = 15 minutes; - } else { - revert("Unsupported chain ID"); - } - skip(minDelay); - - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.execute( - getTransparentUpgradeableProxyAdminAddress(_proxyAddress), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0) // salt - ); - vm.stopPrank(); - } - - function runTransferOwnership(address _proxy) public { - address _newOwner = address(0x1241242151); - bytes memory _data = abi.encodeWithSignature("transferOwnership(address)", _newOwner); - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.schedule( - getTransparentUpgradeableProxyAdminAddress(address(_proxy)), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0), // salt - timelockController.getMinDelay() // delay - ); - vm.stopPrank(); - - uint256 minDelay; - if (block.chainid == 1) { // Mainnet - minDelay = 3 days; - } else if (block.chainid == 17000) { // Holesky - minDelay = 15 minutes; - } else { - revert("Unsupported chain ID"); - } - skip(minDelay); - - vm.startPrank(actors.wallets.YNSecurityCouncil); - timelockController.execute( - getTransparentUpgradeableProxyAdminAddress(address(_proxy)), // target - 0, // value - _data, - bytes32(0), // predecessor - bytes32(0) // salt - ); - vm.stopPrank(); - assertEq(Ownable(getTransparentUpgradeableProxyAdminAddress(address(_proxy))).owner(), _newOwner, "Ownership transfer failed"); - } -} \ No newline at end of file +// UpgradeableBeacon beacon = tokenStakingNodesManager.upgradeableBeacon(); +// address upgradedImplementationAddress = beacon.implementation(); +// assertEq(upgradedImplementationAddress, address(testStakingNodeV2)); + +// // check tokenStakingNodesManager.getAllNodes is the same as before +// ITokenStakingNode[] memory tokenStakingNodesAfter = tokenStakingNodesManager.getAllNodes(); +// assertEq(tokenStakingNodesAfter.length, tokenStakingNodesBefore.length, "TokenStakingNodes length mismatch after upgrade"); +// for (uint i = 0; i < tokenStakingNodesAfter.length; i++) { +// assertEq(address(tokenStakingNodesAfter[i]), address(tokenStakingNodesBefore[i]), "TokenStakingNode address mismatch after upgrade"); +// } + +// runSystemStateInvariants(previousTotalAssets, previousTotalSupply); +// runTransferOwnership(address(tokenStakingNodesManager)); +// } + +// function runUpgradeInvariants( +// address proxyAddress, +// address previousImplementation, +// address newImplementation +// ) internal { +// // Check that the new implementation address is correctly set +// address currentImplementation = getTransparentUpgradeableProxyImplementationAddress(proxyAddress); +// assertEq(currentImplementation, newImplementation, "Invariant: Implementation address should match the new implementation address"); +// // Ensure the implementation address has actually changed +// assertNotEq(previousImplementation, newImplementation, "Invariant: New implementation should be different from the previous one"); +// } + +// function runSystemStateInvariants(uint256 previousTotalAssets, uint256 previousTotalSupply) public { +// uint256 threshold = previousTotalAssets / 1e3; +// assertTrue(compareWithThreshold(yneigen.totalAssets(), previousTotalAssets, threshold), "Total assets integrity check failed"); +// assertEq(yneigen.totalSupply(), previousTotalSupply, "Share mint integrity check failed"); +// } + +// function upgradeContractBatch(address[] memory _proxyAddresses, address[] memory _newImplementations) public { +// require(_proxyAddresses.length == _newImplementations.length, "Arrays must have the same length"); + +// address[] memory targets = new address[](_proxyAddresses.length); +// uint256[] memory values = new uint256[](_proxyAddresses.length); +// bytes[] memory payloads = new bytes[](_proxyAddresses.length); + +// for (uint i = 0; i < _proxyAddresses.length; i++) { +// targets[i] = getTransparentUpgradeableProxyAdminAddress(_proxyAddresses[i]); +// values[i] = 0; +// payloads[i] = abi.encodeWithSignature( +// "upgradeAndCall(address,address,bytes)", +// _proxyAddresses[i], +// _newImplementations[i], +// "" +// ); +// } + +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.scheduleBatch( +// targets, +// values, +// payloads, +// bytes32(0), // predecessor +// bytes32(0), // salt +// timelockController.getMinDelay() // delay +// ); +// vm.stopPrank(); + +// uint256 minDelay; +// if (block.chainid == 1) { // Mainnet +// minDelay = 3 days; +// } else if (block.chainid == 17000) { // Holesky +// minDelay = 15 minutes; +// } else { +// revert("Unsupported chain ID"); +// } +// skip(minDelay); + +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.executeBatch( +// targets, +// values, +// payloads, +// bytes32(0), // predecessor +// bytes32(0) // salt +// ); +// vm.stopPrank(); +// } + +// function upgradeContract(address _proxyAddress, address _newImplementation) public { +// bytes memory _data = abi.encodeWithSignature( +// "upgradeAndCall(address,address,bytes)", +// _proxyAddress, // proxy +// _newImplementation, // implementation +// "" // no data +// ); +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.schedule( +// getTransparentUpgradeableProxyAdminAddress(_proxyAddress), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0), // salt +// timelockController.getMinDelay() // delay +// ); +// vm.stopPrank(); + +// uint256 minDelay; +// if (block.chainid == 1) { // Mainnet +// minDelay = 3 days; +// } else if (block.chainid == 17000) { // Holesky +// minDelay = 15 minutes; +// } else { +// revert("Unsupported chain ID"); +// } +// skip(minDelay); + +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.execute( +// getTransparentUpgradeableProxyAdminAddress(_proxyAddress), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0) // salt +// ); +// vm.stopPrank(); +// } + +// function runTransferOwnership(address _proxy) public { +// address _newOwner = address(0x1241242151); +// bytes memory _data = abi.encodeWithSignature("transferOwnership(address)", _newOwner); +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.schedule( +// getTransparentUpgradeableProxyAdminAddress(address(_proxy)), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0), // salt +// timelockController.getMinDelay() // delay +// ); +// vm.stopPrank(); + +// uint256 minDelay; +// if (block.chainid == 1) { // Mainnet +// minDelay = 3 days; +// } else if (block.chainid == 17000) { // Holesky +// minDelay = 15 minutes; +// } else { +// revert("Unsupported chain ID"); +// } +// skip(minDelay); + +// vm.startPrank(actors.wallets.YNSecurityCouncil); +// timelockController.execute( +// getTransparentUpgradeableProxyAdminAddress(address(_proxy)), // target +// 0, // value +// _data, +// bytes32(0), // predecessor +// bytes32(0) // salt +// ); +// vm.stopPrank(); +// assertEq(Ownable(getTransparentUpgradeableProxyAdminAddress(address(_proxy))).owner(), _newOwner, "Ownership transfer failed"); +// } +// } \ No newline at end of file diff --git a/test/scenarios/ynEIGEN/ynLSDeWithdrawals.t.sol b/test/scenarios/ynEIGEN/ynLSDeWithdrawals.t.sol new file mode 100644 index 000000000..d53651db2 --- /dev/null +++ b/test/scenarios/ynEIGEN/ynLSDeWithdrawals.t.sol @@ -0,0 +1,555 @@ +// SPDX-License-Identifier: BSD 3-Clause License +pragma solidity ^0.8.24; + +import {IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; + +import {ITokenStakingNodesManager} from "src/interfaces/ITokenStakingNodesManager.sol"; +import {ITokenStakingNode} from "src/interfaces/ITokenStakingNode.sol"; +import {IRedeemableAsset} from "src/interfaces/IRedeemableAsset.sol"; +import {IYieldNestStrategyManager} from "src/interfaces/IYieldNestStrategyManager.sol"; + +import {LSDWrapper} from "src/ynEIGEN/LSDWrapper.sol"; +import {RedemptionAssetsVault} from "src/ynEIGEN/RedemptionAssetsVault.sol"; +import {WithdrawalQueueManager} from "src/WithdrawalQueueManager.sol"; + +import {console} from "forge-std/console.sol"; + +import "./ynLSDeScenarioBaseTest.sol"; + +contract ynLSDeWithdrawalsTest is ynLSDeScenarioBaseTest { + + bool private _setup = true; + + address public constant user = address(0x42069); + + ITokenStakingNode public tokenStakingNode; + RedemptionAssetsVault public redemptionAssetsVault; + WithdrawalQueueManager public withdrawalQueueManager; + LSDWrapper public wrapper; + + uint256 public constant AMOUNT = 1 ether; + + function setUp() public virtual override { + + super.setUp(); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + // deal assets to user + { + deal({ token: chainAddresses.lsd.WSTETH_ADDRESS, to: user, give: 1000 ether }); + deal({ token: chainAddresses.lsd.WOETH_ADDRESS, to: user, give: 1000 ether }); + deal({ token: chainAddresses.lsd.SFRXETH_ADDRESS, to: user, give: 1000 ether }); + } + + // deploy RedemptionAssetsVault + { + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address(new RedemptionAssetsVault()), + actors.admin.PROXY_ADMIN_OWNER, + "" + ); + redemptionAssetsVault = RedemptionAssetsVault(payable(address(_proxy))); + } + + // deploy WithdrawalQueueManager + { + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address(new WithdrawalQueueManager()), + actors.admin.PROXY_ADMIN_OWNER, + "" + ); + withdrawalQueueManager = WithdrawalQueueManager(address(_proxy)); + } + + // deploy wrapper + { + // call `initialize` on LSDWrapper + TransparentUpgradeableProxy _proxy = new TransparentUpgradeableProxy( + address( + new LSDWrapper( + chainAddresses.lsd.WSTETH_ADDRESS, + chainAddresses.lsd.WOETH_ADDRESS, + chainAddresses.lsd.OETH_ADDRESS, + chainAddresses.lsd.STETH_ADDRESS) + ), + actors.admin.PROXY_ADMIN_OWNER, + abi.encodeWithSignature("initialize()") + ); + wrapper = LSDWrapper(address(_proxy)); + } + + // initialize RedemptionAssetsVault + { + RedemptionAssetsVault.Init memory _init = RedemptionAssetsVault.Init({ + admin: actors.admin.PROXY_ADMIN_OWNER, + redeemer: address(withdrawalQueueManager), + ynEigen: yneigen, + assetRegistry: assetRegistry + }); + redemptionAssetsVault.initialize(_init); + } + + // initialize WithdrawalQueueManager + { + WithdrawalQueueManager.Init memory _init = WithdrawalQueueManager.Init({ + name: "ynLSDe Withdrawal Manager", + symbol: "ynLSDeWM", + redeemableAsset: IRedeemableAsset(address(yneigen)), + redemptionAssetsVault: redemptionAssetsVault, + admin: actors.admin.PROXY_ADMIN_OWNER, + withdrawalQueueAdmin: actors.ops.WITHDRAWAL_MANAGER, + redemptionAssetWithdrawer: actors.ops.REDEMPTION_ASSET_WITHDRAWER, + requestFinalizer: actors.ops.REQUEST_FINALIZER, + withdrawalFee: 0, + feeReceiver: actors.admin.FEE_RECEIVER + }); + withdrawalQueueManager.initialize(_init); + } + + // upgrade and initialize: + // (1) tokenStakingNode implementation + // (2) ynLSDe + // (3) EigenStrategyManager + // (4) AssetRegistry + // (5) TokenStakingNodesManager + // (6) ynEigenDepositAdapter + _upgradeContracts(); + + // unpause transfers + { + vm.prank(actors.admin.UNPAUSE_ADMIN); + yneigen.unpauseTransfers(); + } + + // grant burner role + { + vm.startPrank(actors.admin.STAKING_ADMIN); + yneigen.grantRole(yneigen.BURNER_ROLE(), address(withdrawalQueueManager)); + vm.stopPrank(); + } + + // top up redemptionAssetsVault + { + address _topper = address(0x420420); + uint256 _amount = 50; // 50 wei + deal({ token: chainAddresses.lsd.WSTETH_ADDRESS, to: _topper, give: _amount }); + deal({ token: chainAddresses.lsd.WOETH_ADDRESS, to: _topper, give: _amount }); + deal({ token: chainAddresses.lsd.SFRXETH_ADDRESS, to: _topper, give: _amount }); + vm.startPrank(_topper); + IERC20(chainAddresses.lsd.WSTETH_ADDRESS).approve(address(redemptionAssetsVault), _amount); + redemptionAssetsVault.deposit(_amount, chainAddresses.lsd.WSTETH_ADDRESS); + IERC20(chainAddresses.lsd.WOETH_ADDRESS).approve(address(redemptionAssetsVault), _amount); + redemptionAssetsVault.deposit(_amount, chainAddresses.lsd.WOETH_ADDRESS); + IERC20(chainAddresses.lsd.SFRXETH_ADDRESS).approve(address(redemptionAssetsVault), _amount); + redemptionAssetsVault.deposit(_amount, chainAddresses.lsd.SFRXETH_ADDRESS); + vm.stopPrank(); + } + + assertApproxEqRel(yneigen.totalAssets(), _totalAssetsBefore, 1e17, "setUp: E0"); // NOTE - not best practice to have it here, but for the time being... + } + + // + // queueWithdrawals + // + + function testQueueWithdrawalSTETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.STETH_STRATEGY_ADDRESS); + uint256 _shares = _strategy.shares((address(tokenStakingNode))); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.queueWithdrawals(_strategy, _shares); + + assertEq(yneigen.totalAssets(), _totalAssetsBefore, "testQueueWithdrawalSTETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), _shares, "testQueueWithdrawalSTETH: E1"); + } + + function testQueueWithdrawalSFRXETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.SFRXETH_STRATEGY_ADDRESS); + uint256 _shares = _strategy.shares((address(tokenStakingNode))); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.queueWithdrawals(_strategy, _shares); + + assertEq(yneigen.totalAssets(), _totalAssetsBefore, "testQueueWithdrawalSFRXETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), _shares, "testQueueWithdrawalSFRXETH: E1"); + } + + function testQueueWithdrawalOETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.OETH_STRATEGY_ADDRESS); + uint256 _shares = _strategy.shares((address(tokenStakingNode))); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.queueWithdrawals(_strategy, _shares); + + assertEq(yneigen.totalAssets(), _totalAssetsBefore, "testQueueWithdrawalOETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), _shares, "testQueueWithdrawalOETH: E1"); + } + + function testQueueWithdrawalsWrongCaller() public { + _setupTokenStakingNode(AMOUNT); + + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.OETH_STRATEGY_ADDRESS); + uint256 _shares = _strategy.shares((address(tokenStakingNode))); + + vm.expectRevert(abi.encodeWithSelector(TokenStakingNode.NotTokenStakingNodesWithdrawer.selector)); + tokenStakingNode.queueWithdrawals(_strategy, _shares); + } + + // + // completeQueuedWithdrawals + // + + function testCompleteQueuedWithdrawalsSTETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + _setup = false; + testQueueWithdrawalSTETH(_amount); + + uint256 _nonce = delegationManager.cumulativeWithdrawalsQueued(address(tokenStakingNode)) - 1; + uint32 _startBlock = uint32(block.number); + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.STETH_STRATEGY_ADDRESS); + uint256 _shares = tokenStakingNode.queuedShares(_strategy); + uint256[] memory _middlewareTimesIndexes = new uint256[](1); + _middlewareTimesIndexes[0] = 0; + + IStrategy[] memory _strategies = new IStrategy[](1); + _strategies[0] = _strategy; + vm.roll(block.number + delegationManager.getWithdrawalDelay(_strategies)); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.completeQueuedWithdrawals(_nonce, _startBlock, _shares, _strategy, _middlewareTimesIndexes, true); + + assertApproxEqAbs(yneigen.totalAssets(), _totalAssetsBefore, 10, "testCompleteQueuedWithdrawalsSTETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), 0, "testCompleteQueuedWithdrawalsSTETH: E1"); + assertApproxEqAbs(tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WSTETH_ADDRESS)), _amount, 100, "testCompleteQueuedWithdrawalsSTETH: E2"); + + } + + function testCompleteQueuedWithdrawalsSFRXETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + _setup = false; + testQueueWithdrawalSFRXETH(_amount); + + uint256 _nonce = delegationManager.cumulativeWithdrawalsQueued(address(tokenStakingNode)) - 1; + uint32 _startBlock = uint32(block.number); + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.SFRXETH_STRATEGY_ADDRESS); + uint256 _shares = tokenStakingNode.queuedShares(_strategy); + uint256[] memory _middlewareTimesIndexes = new uint256[](1); + _middlewareTimesIndexes[0] = 0; + + IStrategy[] memory _strategies = new IStrategy[](1); + _strategies[0] = _strategy; + vm.roll(block.number + delegationManager.getWithdrawalDelay(_strategies)); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.completeQueuedWithdrawals(_nonce, _startBlock, _shares, _strategy, _middlewareTimesIndexes, true); + + assertApproxEqAbs(yneigen.totalAssets(), _totalAssetsBefore, 10, "testCompleteQueuedWithdrawalsSFRXETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), 0, "testCompleteQueuedWithdrawalsSFRXETH: E1"); + assertApproxEqAbs(tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS)), _amount, 100, "testCompleteQueuedWithdrawalsSFRXETH: E2"); + } + + function testCompleteQueuedWithdrawalsOETH(uint256 _amount) public { + if (_setup) _setupTokenStakingNode(_amount); + + _setup = false; + testQueueWithdrawalOETH(_amount); + + uint256 _nonce = delegationManager.cumulativeWithdrawalsQueued(address(tokenStakingNode)) - 1; + uint32 _startBlock = uint32(block.number); + IStrategy _strategy = IStrategy(chainAddresses.lsdStrategies.OETH_STRATEGY_ADDRESS); + uint256 _shares = tokenStakingNode.queuedShares(_strategy); + uint256[] memory _middlewareTimesIndexes = new uint256[](1); + _middlewareTimesIndexes[0] = 0; + + IStrategy[] memory _strategies = new IStrategy[](1); + _strategies[0] = _strategy; + vm.roll(block.number + delegationManager.getWithdrawalDelay(_strategies)); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + tokenStakingNode.completeQueuedWithdrawals(_nonce, _startBlock, _shares, _strategy, _middlewareTimesIndexes, true); + + assertApproxEqAbs(yneigen.totalAssets(), _totalAssetsBefore, 10, "testCompleteQueuedWithdrawalsOETH: E0"); + assertEq(tokenStakingNode.queuedShares(_strategy), 0, "testCompleteQueuedWithdrawalsOETH: E1"); + assertApproxEqAbs(tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WOETH_ADDRESS)), _amount, 100, "testCompleteQueuedWithdrawalsOETH: E2"); + } + + function testCompleteAllWithdrawals(uint256 _amount) public { + _setupTokenStakingNode(_amount); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + _setup = false; + testCompleteQueuedWithdrawalsSTETH(_amount); + testCompleteQueuedWithdrawalsSFRXETH(_amount); + testCompleteQueuedWithdrawalsOETH(_amount); + + assertApproxEqAbs(yneigen.totalAssets(), _totalAssetsBefore, 10, "testCompleteAllWithdrawals: E0"); + } + + // + // processPrincipalWithdrawals + // + + function testProcessPrincipalWithdrawals(uint256 _amount) public { + testCompleteAllWithdrawals(_amount); + + uint256 _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WSTETH_ADDRESS)); + IYieldNestStrategyManager.WithdrawalAction[] memory _actions = new IYieldNestStrategyManager.WithdrawalAction[](3); + _actions[0] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: _availableToWithdraw / 2, + amountToQueue: _availableToWithdraw / 2, + asset: chainAddresses.lsd.WSTETH_ADDRESS + }); + _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WOETH_ADDRESS)); + _actions[1] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: _availableToWithdraw / 2, + amountToQueue: _availableToWithdraw / 2, + asset: chainAddresses.lsd.WOETH_ADDRESS + }); + _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS)); + _actions[2] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: _availableToWithdraw / 2, + amountToQueue: _availableToWithdraw / 2, + asset: chainAddresses.lsd.SFRXETH_ADDRESS + }); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + uint256 _ynEigenWSTETHBalanceBefore = yneigen.assets(chainAddresses.lsd.WSTETH_ADDRESS); + uint256 _ynEigenWOETHBalanceBefore = yneigen.assets(chainAddresses.lsd.WOETH_ADDRESS); + uint256 _ynEigenSFRXETHBalanceBefore = yneigen.assets(chainAddresses.lsd.SFRXETH_ADDRESS); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + eigenStrategyManager.processPrincipalWithdrawals(_actions); + + assertEq(yneigen.totalAssets(), _totalAssetsBefore, "testProcessPrincipalWithdrawals: E0"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.WSTETH_ADDRESS), _availableToWithdraw / 2, 50, "testProcessPrincipalWithdrawals: E1"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.WOETH_ADDRESS), _availableToWithdraw / 2, 50, "testProcessPrincipalWithdrawals: E2"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.SFRXETH_ADDRESS), _availableToWithdraw / 2, 50, "testProcessPrincipalWithdrawals: E3"); + assertApproxEqAbs(yneigen.assets(chainAddresses.lsd.WSTETH_ADDRESS), _ynEigenWSTETHBalanceBefore + _availableToWithdraw / 2, 2, "testProcessPrincipalWithdrawals: E4"); + assertApproxEqAbs(yneigen.assets(chainAddresses.lsd.WOETH_ADDRESS), _ynEigenWOETHBalanceBefore + _availableToWithdraw / 2, 2, "testProcessPrincipalWithdrawals: E5"); + assertEq(yneigen.assets(chainAddresses.lsd.SFRXETH_ADDRESS), _ynEigenSFRXETHBalanceBefore + _availableToWithdraw / 2, "testProcessPrincipalWithdrawals: E6"); + } + + function testProcessPrincipalWithdrawalsNoReinvest(uint256 _amount) public { + testCompleteAllWithdrawals(_amount); + + uint256 _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WSTETH_ADDRESS)); + IYieldNestStrategyManager.WithdrawalAction[] memory _actions = new IYieldNestStrategyManager.WithdrawalAction[](3); + _actions[0] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: 0, + amountToQueue: _availableToWithdraw, + asset: chainAddresses.lsd.WSTETH_ADDRESS + }); + _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.WOETH_ADDRESS)); + _actions[1] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: 0, + amountToQueue: _availableToWithdraw, + asset: chainAddresses.lsd.WOETH_ADDRESS + }); + _availableToWithdraw = tokenStakingNode.withdrawn(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS)); + _actions[2] = IYieldNestStrategyManager.WithdrawalAction({ + nodeId: tokenStakingNode.nodeId(), + amountToReinvest: 0, + amountToQueue: _availableToWithdraw, + asset: chainAddresses.lsd.SFRXETH_ADDRESS + }); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + uint256 _ynEigenWSTETHBalanceBefore = yneigen.assets(chainAddresses.lsd.WSTETH_ADDRESS); + uint256 _ynEigenWOETHBalanceBefore = yneigen.assets(chainAddresses.lsd.WOETH_ADDRESS); + uint256 _ynEigenSFRXETHBalanceBefore = yneigen.assets(chainAddresses.lsd.SFRXETH_ADDRESS); + + vm.prank(actors.ops.WITHDRAWAL_MANAGER); + eigenStrategyManager.processPrincipalWithdrawals(_actions); + + assertEq(yneigen.totalAssets(), _totalAssetsBefore, "testProcessPrincipalWithdrawalsNoReinvest: E0"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.WSTETH_ADDRESS), _availableToWithdraw, 50, "testProcessPrincipalWithdrawalsNoReinvest: E1"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.WOETH_ADDRESS), _availableToWithdraw, 50, "testProcessPrincipalWithdrawalsNoReinvest: E2"); + assertApproxEqAbs(redemptionAssetsVault.balances(chainAddresses.lsd.SFRXETH_ADDRESS), _availableToWithdraw, 50, "testProcessPrincipalWithdrawalsNoReinvest: E3"); + assertEq(yneigen.assets(chainAddresses.lsd.WSTETH_ADDRESS), _ynEigenWSTETHBalanceBefore, "testProcessPrincipalWithdrawalsNoReinvest: E4"); + assertEq(yneigen.assets(chainAddresses.lsd.WOETH_ADDRESS), _ynEigenWOETHBalanceBefore, "testProcessPrincipalWithdrawalsNoReinvest: E5"); + assertEq(yneigen.assets(chainAddresses.lsd.SFRXETH_ADDRESS), _ynEigenSFRXETHBalanceBefore, "testProcessPrincipalWithdrawalsNoReinvest: E6"); + } + + // + // requestWithdrawal + // + + function testRequestWithdrawal(uint256 _amount) public { + testProcessPrincipalWithdrawalsNoReinvest(_amount); + + uint256 _totalAssetsBefore = yneigen.totalAssets(); + + uint256 _userYnLSDeBalance = yneigen.balanceOf(user); + vm.startPrank(user); + yneigen.approve(address(withdrawalQueueManager), _userYnLSDeBalance); + uint256 _tokenId = withdrawalQueueManager.requestWithdrawal(_userYnLSDeBalance); + vm.stopPrank(); + + assertApproxEqAbs( + withdrawalQueueManager.pendingRequestedRedemptionAmount(), + assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.WSTETH_ADDRESS), _amount) + assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.WOETH_ADDRESS), _amount) + assetRegistry.convertToUnitOfAccount(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS), _amount), + 1000, + "testRequestWithdrawal: E0" + ); + assertEq(_tokenId, 0, "testRequestWithdrawal: E1"); + assertEq(_totalAssetsBefore, yneigen.totalAssets(), "testRequestWithdrawal: E2"); + } + + // + // claimWithdrawal + // + + function testClaimWithdrawal(uint256 _amount) public { + testRequestWithdrawal(_amount); + + vm.prank(actors.ops.REQUEST_FINALIZER); + withdrawalQueueManager.finalizeRequestsUpToIndex(1); + + uint256 _userWSTETHBalanceBefore = IERC20(chainAddresses.lsd.WSTETH_ADDRESS).balanceOf(user); + uint256 _userWOETHBalanceBefore = IERC20(chainAddresses.lsd.WOETH_ADDRESS).balanceOf(user); + uint256 _userSFRXETHBalanceBefore = IERC20(chainAddresses.lsd.SFRXETH_ADDRESS).balanceOf(user); + uint256 _totalAssetsBefore = yneigen.totalAssets(); + uint256 _redemptionRateBefore = redemptionAssetsVault.redemptionRate(); + + vm.prank(user); + withdrawalQueueManager.claimWithdrawal(0, user); + + assertApproxEqRel(IERC20(chainAddresses.lsd.WSTETH_ADDRESS).balanceOf(user), _userWSTETHBalanceBefore + _amount, 1, "testClaimWithdrawal: E0"); + assertApproxEqRel(IERC20(chainAddresses.lsd.WOETH_ADDRESS).balanceOf(user), _userWOETHBalanceBefore + _amount, 1, "testClaimWithdrawal: E1"); + assertApproxEqRel(IERC20(chainAddresses.lsd.SFRXETH_ADDRESS).balanceOf(user), _userSFRXETHBalanceBefore + _amount, 1, "testClaimWithdrawal: E2"); + assertLt(yneigen.totalAssets(), _totalAssetsBefore, "testClaimWithdrawal: E3"); + assertApproxEqRel(redemptionAssetsVault.redemptionRate(), _redemptionRateBefore, 1, "testClaimWithdrawal: E4"); + } + + // + // internal helpers + // + + function _setupTokenStakingNode(uint256 _amount) private { + vm.assume(_amount > 10_000 && _amount < 100 ether); + + vm.prank(actors.ops.STAKING_NODE_CREATOR); + tokenStakingNode = tokenStakingNodesManager.createTokenStakingNode(); + + uint256 _len = 3; + IERC20[] memory _assetsToDeposit = new IERC20[](_len); + _assetsToDeposit[0] = IERC20(chainAddresses.lsd.WSTETH_ADDRESS); + _assetsToDeposit[1] = IERC20(chainAddresses.lsd.WOETH_ADDRESS); + _assetsToDeposit[2] = IERC20(chainAddresses.lsd.SFRXETH_ADDRESS); + + uint256[] memory _amounts = new uint256[](_len); + _amounts[0] = _amount; + _amounts[1] = _amount; + _amounts[2] = _amount; + + vm.startPrank(user); + for (uint256 i = 0; i < _len; i++) { + _assetsToDeposit[i].approve(address(yneigen), _amounts[i]); + yneigen.deposit(_assetsToDeposit[i], _amounts[i], user); + } + vm.stopPrank(); + + vm.startPrank(actors.ops.STRATEGY_CONTROLLER); + eigenStrategyManager.stakeAssetsToNode(tokenStakingNode.nodeId(), _assetsToDeposit, _amounts); + vm.stopPrank(); + } + + function _upgradeContracts() internal { + + address[] memory _proxyAddresses = new address[](3); + _proxyAddresses[0] = address(yneigen); + _proxyAddresses[1] = address(assetRegistry); + _proxyAddresses[2] = address(tokenStakingNodesManager); + address[] memory _newImplementations = new address[](3); + _newImplementations[0] = address(new ynEigen()); + _newImplementations[1] = address(new AssetRegistry()); + _newImplementations[2] = address(new TokenStakingNodesManager()); + + address[] memory targets = new address[](6); + uint256[] memory values = new uint256[](6); + bytes[] memory payloads = new bytes[](6); + bytes32 predecessor = bytes32(0); + bytes32 salt = bytes32(0); + uint256 delay = timelockController.getMinDelay(); + + for (uint256 i = 0; i < _proxyAddresses.length; i++) { + bytes memory _data = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + _proxyAddresses[i], // proxy + _newImplementations[i], // implementation + "" + ); + targets[i] = getTransparentUpgradeableProxyAdminAddress(_proxyAddresses[i]); + values[i] = 0; + payloads[i] = _data; + } + + targets[3] = address(tokenStakingNodesManager); + values[3] = 0; + payloads[3] = abi.encodeWithSignature( + "upgradeTokenStakingNode(address)", + new TokenStakingNode() + ); + + targets[4] = getTransparentUpgradeableProxyAdminAddress(address(eigenStrategyManager)); + values[4] = 0; + payloads[4] = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + address(eigenStrategyManager), // proxy + address(new EigenStrategyManager()), // implementation + abi.encodeWithSignature( + "initializeV2(address,address,address)", + address(redemptionAssetsVault), + address(wrapper), + actors.ops.WITHDRAWAL_MANAGER + ) + ); + + targets[5] = getTransparentUpgradeableProxyAdminAddress(address(ynEigenDepositAdapter_)); + values[5] = 0; + payloads[5] = abi.encodeWithSignature( + "upgradeAndCall(address,address,bytes)", + ynEigenDepositAdapter_, // proxy + address(new ynEigenDepositAdapter()), // implementation + abi.encodeWithSignature("initializeV2(address)", address(wrapper)) + ); + + vm.prank(actors.wallets.YNSecurityCouncil); + timelockController.scheduleBatch(targets, values, payloads, predecessor, salt, delay); + + skip(delay); + + vm.prank(actors.wallets.YNSecurityCouncil); + timelockController.executeBatch(targets, values, payloads, predecessor, salt); + } +} \ No newline at end of file diff --git a/test/scenarios/ynEigen.spec.sol b/test/scenarios/ynEigen.spec.sol index cefcf7efa..7301296af 100644 --- a/test/scenarios/ynEigen.spec.sol +++ b/test/scenarios/ynEigen.spec.sol @@ -183,7 +183,7 @@ contract YnEIGENScenarioTest3 is ynEigenIntegrationBaseTest { address user1 = address(0x01); - function test_ynETH_Scenario_3_Deposit() public { + function test_ynEigen_Scenario_3_Deposit() public { depositLSD_and_createNode(); } @@ -214,6 +214,6 @@ contract YnEIGENScenarioTest3 is ynEigenIntegrationBaseTest { eigenStrategyManager.stakeAssetsToNode(nodeId, assets, amounts); } - assertApproxEqAbs(amount, eigenStrategyManager.getStakedAssetBalanceForNode(asset, 0), 2); + assertApproxEqAbs(amount, eigenStrategyManager.getStakedAssetBalanceForNode(asset, 0), 5); } } \ No newline at end of file